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 分钟前
虚拟机复制过来运行时:“虚拟机使用的此版本,VMware Workstation 不支持的硬件版本。”错误解决办法,亲测可用
linux·运维·服务器·后端
Wang's Blog14 分钟前
Java 中间件之 RabbitMQ 快速入门: MQ 常见技术选型对比
java·中间件·java-rabbitmq
蜗牛互联网15 分钟前
Java Agent 工具调用的 allowlist、参数校验与调用预算
java·开发语言·人工智能·后端·oracle
用户8132679332515 分钟前
行情数据晚到几秒,会让量化策略失去优势吗?从信号时间到回测偏差
后端·github·api
大文说跨境15 分钟前
多账号环境隔离方案技术选型:指纹浏览器、VPS 与云手机的三种架构对比
java·开发语言·前端
九零HTTP16 分钟前
一次 TCP 连接的一生:从三次握手到四次挥手
后端
ZOnePieceC20 分钟前
消息队列之Kafka
后端
yunwei3720 分钟前
eBPF 入门实践教程十七:编写 eBPF 程序统计随机/顺序磁盘 I/O
linux·后端·性能优化
花间相见21 分钟前
【计算基础|网络07】HTTPS(下):ECDHE 握手与优化
后端
QuantiCore_IO22 分钟前
从请求风暴到可维护的数据管道:量化系统为什么需要批量接口?
后端·github·api