【Java 基础】@Bean 注解在 @Configuration 和 在 @Component 下的区别

区别就是:

@Configuration 中所有带 @Bean 注解的方法都会被动态代理(cglib 动态代理调用方法时重写成从 Spring 上下文中获取 bean),因此调用该方法返回的都是同一个实例,可以保证单例。 @Component 注解就是 new 一个新对象。

一、起因

当我在项目中看到 @Bean 注解的es创建客户端的方法放在了 @Component中,而不是放在 @Configuration 中,所以我就进一步查询了 @Bean 注解放在这两个注解里的区别

二、代码测试案例1

MyTestConfig 类:

@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;
    }

}

测试类:

@SpringBootTest
class QuartzDemoApplicationTests {

    @Autowired
    private Car car;

    @Autowired
    private Driver driver;

    @Test
    public void a2() {
        boolean result = driver.getCar() == car;
        System.out.println(result ? "同一个car" : "不同的car");
    }

}

打印结果:

同一个car

MyTestConfig 类中 @Configuration 注解替换为 @Component 注解后的打印结果:

不同的car

从上面的结果可以发现:

跳过源码解读,虽然 @Component 注解也会当做配置类,但是并不会为其生成 CGLIB 代理 Class,所以在生成 Driver 对象时和生成 Car 对象时调用 car() 方法执行了两次 new 操作,所以是不同的对象。当使用 @Configuration 注解时,生成当前对象的子类 Class,并对方法拦截,第二次调用 car() 方法时直接从 BeanFactory 之中获取对象,所以得到的是同一个对象。

三、代码测试案例2

MyConfiguration 类:

@Configuration
public class MyConfiguration {

    // myBean 方法名与返回类名一致,首字母小写
    @Bean
    public MyBean myBean() {
        MyBean myBean = new MyBean();
        myBean.setPort("8080");
        return myBean;
    }

}

测试类:

@SpringBootTest
class QuartzDemoApplicationTests {

    @Autowired
    private MyConfiguration myConfiguration;

    @Test
    public void a2() {

        MyBean myBean3 = myConfiguration.myBean();
        System.out.println(myBean3.get());
        System.out.println(myBean3);

        MyBean myBean4 = myConfiguration.myBean();
        System.out.println(myBean4.get());
        System.out.println(myBean4);
    }

}

打印结果:

端口号:8080
com.example.quartzdemo.config.MyBean@7718a40f
端口号:8080
com.example.quartzdemo.config.MyBean@7718a40f

MyConfiguration 类中 @Configuration 注解替换为 @Component 注解后的打印结果:

端口号:8080
com.example.quartzdemo.config.MyBean@288ca5f0
端口号:8080
com.example.quartzdemo.config.MyBean@4068102e

四、参考文档

  •  Spring @Configuration 和 @Component 区别
  •  @Component和@Configuration作为配置类的差别

你可能感兴趣的:(springboot,java基础,java,java,开发语言,后端)