spring的IOC与DI

一.IOC与AOP

1.IOC(控制反转):,将对象的创建与依赖关系交给spring容器进行管理,不用自己在代码里面new,避免了之前"一次修改牵动全身"的情况

**2.AOP(面向切面编程):**把多个模块的通用逻辑提取,他通过代理机制动态注入目标方法上,避免到处复制粘贴使其冗余

二.DI

1.DI(依赖注入)

首先Bean对象就是交给spring进行管理的对象,将Bean对象从容器拿出并注入对应的对象就是DI注入

2.通过上下文管理器从容器拿到Bean对象

java 复制代码
// 交给 spring进行管理
@Configuration
public class Config {
    public void func(){
        System.out.println("调用的是Config里面的方法");
    }
}

a.getBean(.class对象)

要求:同类型的Bean对象必须唯一,不需要强转,当同类型Bean的数量>1会抛异常

java 复制代码
@SpringBootApplication
public class DemoApplication {
	public static void main(String[] args) {
		ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
		Config bean = run.getBean(Config.class);
		bean.func();
	}
}
// 结果>: 调用的是Config里面的方法

b.getBena(String)

要求:对同类型的Bean数量没有要求,但是需要强转

java 复制代码
@SpringBootApplication
public class DemoApplication {
	public static void main(String[] args) {
		ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
		Config bean = (Config) run.getBean("config");
		bean.func();
	}
}
// 结果是>: 调用的是Config里面的方法

c.getBean(String,,class对象)

要求:对同类的Bean数量没有要求,不需要强转

java 复制代码
@SpringBootApplication
public class DemoApplication {
	public static void main(String[] args) {
		ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
		Config bean = run.getBean("config", Config.class);
		bean.func();
	}
}
// 结果是>: 调用的是Config里面的方法

3.ApplicationContext VS BeanFactory

当我们点击去getBean

发现是BeanFactory提供的方法,那和上下管理器ApplicationContext的区别>:

4.DI注入的方式

a.@AutoWired与@Recourse

java 复制代码
@Component
public class UseBean {
    @Autowired
    private Config config;

    public void func(){
        System.out.println("调用UseBean的func方法");
        config.func();
    }
}
java 复制代码
@SpringBootApplication
public class DemoApplication {
	public static void main(String[] args) {
		ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
		UseBean bean = run.getBean("useBean", UseBean.class);
		bean.func();
	}
}

结果>:

调用UseBean的func方法

调用的是Config里面的方法

后面将@AutoWired变为@Resource,其余代码不动,

结果是>:

调用UseBean的func方法

调用的是Config里面的方法

都可以注入,其中两个注解的的区别是面试常考题之一,详细看下面

b.通过构造方法注入

情况1:当只有一个构造方法时,不用加注解

java 复制代码
@Component
public class UseBean {
    private final Config config;

    public UseBean(Config config){
        this.config = config;
    }

    public void func(){
        System.out.println("调用UseBean的func方法");
        config.func();
    }
}

在其它代码不变.修改useBean代码后的结果>:

调用UseBean的func方法

调用的是Config里面的方法

**情况2:**当有多个构造方法,若是有无参的构造方法,加注解(@AutoWired)

java 复制代码
@Component
public class UseBean {
    private final Config config;
    public Integer num;

    public UseBean(){
        this.config = null;
    }
    @Autowired
    public UseBean(Config config){
        this.config = config;
    }

    public void func(){
        System.out.println("调用UseBean的func方法");
        System.out.println("num的值为:"+num);
        config.func();
    }
}

有时会看到这样写法>:

结果是:

1.@Autowired 写在构造参数上是无效的

2.没有在构造方法加注解,此时不知道用哪一个,就会去用无参的构造方法

所以结果显示找不到无参的方法

c.通过setter方法注入

只修改UseBean里面的代码

java 复制代码
@Component
public class UseBean {
    private Config config;

//    @Resource
    @Autowired
    public void setConfig(Config config){
        this.config = config;
    }

    public void func(){
        System.out.println("调用UseBean的func方法");
        config.func();
    }
}

结果显示>:

调用UseBean的func方法

调用的是Config里面的方法

d.通过普通方法注入

java 复制代码
@Component
public class UseBean {
    private Config config;

//    @Autowired
    @Resource
    public void normalFunc(Config config){
        this.config = config;
    }

    public void func(){
        System.out.println("调用UseBean的func方法");
        config.func();
    }
}

结果是>:

调用UseBean的func方法

调用的是Config里面的方法

e.接口回调注入

**注意>:**需要去实现内置的spring里面的Aware接口,如:BeanFactoryAware、ApplicationContextAware,此时spring会自动回调注入对应的组件

java 复制代码
public class UseBean {
    private Config config;
    public UseBean(Config config){
        this.config = config;
    }
    public void func(){
        System.out.println("调用UseBean的func方法");
        config.func();
    }
}

实现BeanFactoryAware>:

java 复制代码
@Component
public class MyCompoment implements BeanFactoryAware {
    private Config config;
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.config = beanFactory.getBean("config",Config.class);
        UseBean u = new UseBean(config);
        u.func();
    }
}

结果>:

调用UseBean的func方法

调用的是Config里面的方法


实现ApplicationContextAware>:

java 复制代码
@Component
public class MyCompoment implements ApplicationContextAware {

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        UseBean bean = applicationContext.getBean("useBean", UseBean.class);
		bean.func();
    }
}

结果>:

调用UseBean的func方法

调用的是Config里面的方法

5.总结

其中第四个普通方法注入,也是不可以注入final修饰的对象,而且与setter一样容易修改

第五个,用得少,这里就列举一些接口,后面需要用到再去查找

问题:@Autowired与@Resource区别

1.@Autowried是spring框架提供的注解,而@Recourse是JDK提供的注解

2. @AutoWried是按照类型 进行注入,而@Resource是按照名称注入

3.@Resource支持更多的参数类型,例如: name 设置,在根据名称获取Bean


**小知识:**虽然 @Autowired 注解按照类型匹配,没有就看 @Qualifier定义的name,但实际上没有 @Qualifier 注解就会按照自己的 name 查找!

相关推荐
神奇小汤圆3 小时前
MySQL慢查询优化案例:真实案例+EXPLAIN分析——性能提升10倍!
后端
云烟成雨TD3 小时前
Spring AI Alibaba 1.x 系列【53】Interrupts 中断机制:动态中断
java·人工智能·spring
还没学会摸鱼的钓鱼仔3 小时前
手撕 LangChain Deep Agents 源码 (一):create_deep_agent 是如何"组装"出一个 AI 操作系统的
后端
用户298698530143 小时前
Java 操作 Word 文档:数学公式与符号的插入方法
java·后端
见青..3 小时前
JAVA安全靶场环境搭建
java·web安全·靶场·java安全
一坨阿亮3 小时前
Docker 离线部署
java·spring cloud·docker
小撒的私房菜3 小时前
Day 5:Agent Loop——整个系列里最关键的一天
人工智能·后端
XovH3 小时前
Django 模型(Model)设计:无需 SQL,用 Python 类定义你的数据库
后端
传说之后3 小时前
Go 调用 OpenAI 兼容 API:对话、流式输出、上下文与图片识别
后端