• 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,是多实例的。

  • 相关阅读:
    Linux PostgreSQL离线下载与安装
    5-什么是猴子补丁,有什么用途?什么是反射,python中如何使用反射?http和https的区别?
    “蔚来杯“2022牛客暑期多校训练营9 F题: Matrix and GCD
    企业级容器云PaaS解决方案【厚PaaS+轻应用+微服务】---(2)
    压缩算法---以golang/snappy为例
    调用ros系统摄像头可视化rqt工具
    【Spring】AOP相关、五种增强方式、IoC与AOP注解开发、纯注解开发
    DSPE-PEG-TAT,磷脂-聚乙二醇-靶向穿膜肽,脂质体修饰细胞穿膜肽TAT
    leetcode: 410. 分割数组的最大值
    管易云·奇门与金蝶云星空对接集成历史发货单查询打通销售出库新增
  • 原文地址:https://blog.csdn.net/weixin_45163291/article/details/139265833