@Configuration 与 @Bean
@Configuration:
相当于传统的xml配置文件,如果有些第三方库需要用到xml文件,建议通过@Configuration类作为项目的配置主类,可以使用@ImportResource注解加载xml配置文件。
作用:类
@Bean:
用@Bean标注方法等价于XML中配置的bean。声明某个方法产生一个Bean交给Spring容器管理。
作用:注解只能用在方法或者注解上
项目中通常会看到@Configuration与@Bean两个注解组合起来使用,那么就会想@Bean单独使用又是什么效果呢?
写个demo...测试一下
首先写BeanA 、BeanB,并且设置依赖关系
public class BeanA {
}
public class BeanB {
private BeanA beanA;
public BeanB(BeanA beanA) {
this.beanA = beanA;
}
}
分别获取一下BeanA 、BeanB
/**
* @author high
* @version 1.0.0
* @date 2023/4/2 13:40
*/
@Configuration
public class TestBean {
@Bean
public BeanA BeanA() {
System.out.println("BeanA");
return new BeanA();
}
@Bean
public BeanB BeanB(){
System.out.println("BeanB");
return new BeanB(this.BeanA());
}
}
测试:
/**
* @author high
* @version 1.0.0
* @date 2023/4/2 13:51
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class BeanTests {
@Test
public void beansTest() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestBean.class);
for (String beanName : context.getBeanDefinitionNames()) {
System.out.println(beanName + ":" + context.getBean(beanName));
}
}
}
没有使用@Configuration的结果:
调用了BeanA
BeanB
调用了BeanA
BeanB1
调用了BeanA
org.springframework.context.annotation.internalConfigurationAnnotationProcessor:org.springframework.context.annotation.ConfigurationClassPostProcessor@5fef0c19
org.springframework.context.annotation.internalAutowiredAnnotationProcessor:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@2e6d76ba
org.springframework.context.annotation.internalCommonAnnotationProcessor:org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@22a6d75c
org.springframework.context.event.internalEventListenerProcessor:org.springframework.context.event.EventListenerMethodProcessor@5a9840f3
org.springframework.context.event.internalEventListenerFactory:org.springframework.context.event.DefaultEventListenerFactory@7d30007d
testBean:com.springwork.high.config.TestBean@382d71c7
BeanA:com.springwork.high.config.BeanA@2ca54da9
BeanB:BeanB{beanA=com.springwork.high.config.BeanA@34a20f16}
BeanB1:BeanB{beanA=com.springwork.high.config.BeanA@496cc217}
使用了@Configuration的结果
调用了BeanA
BeanB
BeanB1
org.springframework.context.annotation.internalConfigurationAnnotationProcessor:org.springframework.context.annotation.ConfigurationClassPostProcessor@22a6d75c
org.springframework.context.annotation.internalAutowiredAnnotationProcessor:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@5a9840f3
org.springframework.context.annotation.internalCommonAnnotationProcessor:org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@7d30007d
org.springframework.context.event.internalEventListenerProcessor:org.springframework.context.event.EventListenerMethodProcessor@382d71c7
org.springframework.context.event.internalEventListenerFactory:org.springframework.context.event.DefaultEventListenerFactory@2ca54da9
testBean:com.springwork.high.config.TestBean$$EnhancerBySpringCGLIB$$914db2f7@34a20f16
BeanA:com.springwork.high.config.BeanA@496cc217
BeanB:BeanB{beanA=com.springwork.high.config.BeanA@496cc217}
BeanB1:BeanB{beanA=com.springwork.high.config.BeanA@496cc217}
对比结果可以看出有@Configuration的类时,@Bean修饰的方法都只被调用了一次
总结:
@Configuration注解修饰的类,会被spring通过cglib做增强处理,动态生成一个代理对象,代理会拦截所有被@Bean注解修饰的方法,可以确保这些bean是单例的
@Configuration与@Component
@component
泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
以上的配置不变,将@Configuration改成@Component运行程序
调用了BeanA
BeanB
调用了BeanA
BeanB1
调用了BeanA
org.springframework.context.annotation.internalConfigurationAnnotationProcessor:org.springframework.context.annotation.ConfigurationClassPostProcessor@50598a1a
org.springframework.context.annotation.internalAutowiredAnnotationProcessor:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@14de1901
org.springframework.context.annotation.internalCommonAnnotationProcessor:org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@437ed416
org.springframework.context.event.internalEventListenerProcessor:org.springframework.context.event.EventListenerMethodProcessor@11f23038
org.springframework.context.event.internalEventListenerFactory:org.springframework.context.event.DefaultEventListenerFactory@de77146
testBean:com.springwork.high.config.TestBean@691567ea
BeanA:com.springwork.high.config.BeanA@5cfed0ba
BeanB:BeanB{beanA=com.springwork.high.config.BeanA@5c8d58ed}
BeanB1:BeanB{beanA=com.springwork.high.config.BeanA@6a567f7b}
从结果可以看出@Component注解并没有通过 cglib 来代理@Bean
方法的调用。