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 查找!

相关推荐
学以智用2 小时前
.NET Core 部署上线完整教程(Windows IIS / Linux / Docker)
后端·.net
爱丽_2 小时前
AQS 的 CLH 同步队列:入队/出队、park/unpark 与“公平性”从哪来
java·开发语言·jvm
共享家95272 小时前
实现简化的高性能并发内存池
开发语言·数据结构·c++·后端
鱼鳞_2 小时前
Java学习笔记_Day15
java·笔记·学习·排序算法
用户608186527902 小时前
WPF 命令 ICommand 从原理到实战
后端
liuqun03192 小时前
go进阶之gc
开发语言·后端·golang
李小狼lee2 小时前
以一个简单案例来讲解RAG
后端
鹏程十八少2 小时前
8. Android 深入插件化Shadow源码:揭秘插件Activity启动的完整链路(源码解析)
java·前端·面试
程序员清风2 小时前
OpenAI创始人学AI的底层逻辑,普通人照着做就能上手!
java·后端·面试