注释首先咱们都晓得应用 Spring 的 @ComponentScan 注解能够扫描到 @Configuration 和 @Component 的类,并将其交由 Spring 容器治理,默认会放入单例池中。
新建了一个 BeanConfig 类用来测试后果:
@Configuration
public class BeanConfig {}
复制代码
通过上下文获取 IOC 容器中的 BeanConfig,发现的确是被 CGLIB 进行了代理。
执行查看上下文中 beanFactory 的单例池中的确存在。
将 BeanConfig 类的 @Configuration 注解改为 @Component 后再看一下则显示没有被 CGLIB 代理。
问题
那么 Spring 为什么设计 @Configuration 注解润饰的 Bean 要被动静代理?
先说后果:Spring 的目标是让 @Configuration 注解的类中被 @Bean 注解的办法生成的对象是单例,那如何使一个办法每次生成返回的对象都是同一个,代理就是其中一种形式。
首先 @Configuration 注解的作用是用于定义配置类来替换 XML 配置文件,被注解的类外部蕴含有一个或多个被 @Bean 注解的办法,这些办法会被用于构建 BeanDefinition,初始化 Spring 容器。
也就是说 @Configuration 的次要目标是搭配 @Bean 注解代替 XML 配置文件来向 Spring 容器注入 Bean。咱们在 BeanConfig 类中减少两个 @Bean 注解的办法:
@Configuration
public class BeanConfig {//@Scope("prototype")
@Bean
public Role role(){return new Role();
}
@Bean
public User user(){Role r1=role();
Role r2=role();
System.out.println(r1==r2);
return new User();}} 复制代码
通过 Spring 的解决,间接调用 @Configuration 注解中 bean 办法,获取的就是同一个对象,这样想要间接应用某个 @Bean 注解的对象就不须要 @Autowired 注入了。
当然你非要在办法上加上注解 @Scope(“prototype”),每次调用该办法还是会生成不同的对象。
源码
注解配置读取器:向 BeanDefinitionMap 中增加了 7 个元素,其中一个就是 ConfigurationClassPostProcessororg.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext() 执行所有的 BeanFactoryPostProcessor 的 postProcessorBeanFactory() 办法 org.springframework.context.support.AbstractApplicationContext#refresh() 办法中的 invokeBeanFactoryPostProcessors(beanFactory)org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanFactory 查找到所有带有 @Configuration 注解的 bean 定义,而后在第二个 for 循环中对类进行加强 org.springframework.context.annotation.ConfigurationClassPostProcessor#enhanceConfigurationClasses
总结
加了 @Configuration 的类会被 CGLIB 进行动静代理,不加或者加 @Component 注解则不会被代理。