• spring boot @Configuration和@Componment的区别


    • @Configuration
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface Configuration {
        @AliasFor(
            annotation = Component.class
        )
        String value() default "";
    }
    
    public class Car {
    
        private int id;
    
        private String name;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    }
    
    public class Driver {
    
        private int id;
    
        private String name;
    
        private Car car;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Car getCar() {
            return car;
        }
    
        public void setCar(Car car) {
            this.car = car;
        }
    
    }
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MyTestConfig {
    
        @Bean
        public Driver driver() {
            Driver driver = new Driver();
            driver.setId(1);
            driver.setName("driver");
            driver.setCar(car());
            return driver;
        }
    
        @Bean
        public Car car() {
            Car car = new Car();
            car.setId(1);
            car.setName("car");
            return car;
        }
    
    }
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Component
    public class MyTestConfig {
        @Bean
        public Driver driver() {
            Driver driver = new Driver();
            driver.setId(1);
            driver.setName("driver");
            driver.setCar(car());
            return driver;
        }
        @Bean
        public Car car() {
            Car car = new Car();
            car.setId(1);
            car.setName("car");
            return car;
        }
    
    }
    
    • 上面两段代码除MyTestConfig类上的注解不同之外其他都相同,但Spring对两者的处理方式是完全不一样的。

    • 第一段代码会像我们期望的一样正常运行,因为driver()这段代码中driver.setCar(car())方法会由Spring代理执行,
      Spring发现方法所请求的Bean已经在容器中,那么就直接返回容器中的Bean。所以全局只有一个Car对象的实例。

      第二段代码在执行driver()
      时driver.setCar(car())不会被Spring代理,会直接调用car()方法获取一个全新的Car对象实例,所以全局会有多个Car对象的实例
      造成这种差异的原因如下: 概括就是 @Configuration 中所有带 @Bean
      注解的方法都会被动态代理,因此调用该方法返回的都是同一个实例。

      其工作原理是:如果方式是首次被调用那么原始的方法体会被执行并且结果对象会被注册到Spring上下文中,之后所有的对该方法的调用仅仅只是从Spring上下文中取回该对象返回给调用者。
      在上面的第二段代码中,driver.setCar(car())只是纯JAVA方式的调用,多次调用该方法返回的是不同的对象实例。
      要修正第二段代码中的问题,可以使用@Autowired如下所示:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Component;
    
    //@Configuration
    @Component
    public class MyTestConfig2 {
    
        @Autowired
        Car car;
        
        @Bean
        public Driver driver() {
            Driver driver = new Driver();
            driver.setId(1);
            driver.setName("driver");
            driver.setCar(car);
            return driver;
        }
    
        @Bean
        public Car car() {
            Car car = new Car();
            car.setId(1);
            car.setName("car");
            return car;
        }
    
    }
    

    总结:
    1. 通过@Configuration或者@Componment注解的类默认是非懒加载,可以使用@Lazy或者在@Bean上@Lazy开启懒加载;
    2. 通过@Configuration注解的类默认会被CGLIB动态代理,所有被 @Bean 注解标记的方法将来都是通过代理方法进行调用,在该类中使用@Bean时为单列;
    3. 通过@Componment注解的类默认不会产生动态代理,在该类中使用@Bean,是多实例的。

  • 相关阅读:
    【语音通信】语音通信系统包括语音硬件采样,抽样量化,PCM编码解码模块,FIR滤波,QPSK调制解调模块,语音增强模块以及语音信号还原
    系列二、Shiro的核心组件
    leetcode刷题 (9.11) 二叉树
    最新IE跳转Edge浏览器解决办法(2024.2.26)
    文章参考链接
    再来了解机器学习和深度学习_有监督机器学习_无监督机器学习---人工智能工作笔记0018
    centos统计子目录和文件的大小并排序
    JAVA毕业设计剧院售票系统计算机源码+lw文档+系统+调试部署+数据库
    【Leetcode小解析】正则表达式匹配
    快速实现MQTT协议网关网口连接西门子PLC
  • 原文地址:https://blog.csdn.net/weixin_45163291/article/details/139265833