日期:
来源:SpringForAll收集编辑:
来源:cnblogs.com/youzhibing/p/15354706.html
疑虑背景
疑虑描述
@Configuration 加 @Bean 会创建一个 userName 不为 null 的 UserManager 对象,而 @Component 也会创建一个 userName 为 null 的 UserManager 对象Spring Boot 版本
2.0.3.RELEASE结果验证
@Configuration 加 @Bean 创建的 userName 不为 null 的 UserManager 对象@Component 创建的 userName 为 null 的 UserManager 对象?源码解析
@Configuration 与 @Component 关系很紧密@Configuration 能够被 component scanConfigurationClassPostProcessor 与@Configuration 息息相关,其类继承结构图如下:BeanFactoryPostProcessor 接口和 PriorityOrdered 接口,关于 BeanFactoryPostProcessor,AbstractApplicationContext 的 refresh 方法调用的 invokeBeanFactoryPostProcessors(beanFactory)开始,来跟下源码com.lee.qsl 包下的 component scan , com.lee.qsl 包及子包下的 UserConfig 、 UserController 和 UserManager 都被扫描出来@Bean 的处理还未开始, UserManager 是通过@Component 而被扫描出来的;此时 Spring 容器中 beanDefinitionMap 中的 UserManager 是这样的ConfigurationClass ,递归扫描 BeanDefinitionconfigClassesUserConfig bean 定义信息中 beanMethods 中有一个元素 [BeanMethod:name=userManager,declaringClass=com.lee.qsl.config.UserConfig]@Component 修饰的 UserManager 定义直接被覆盖成了 @Configuration + @Bean 修饰的 UserManager 定义ScannedGenericBeanDefinition 替换成了 ConfigurationClassBeanDefinitionBeanDefinition 创建实例的时候,创建的自然就是 @Configuration + @Bean 修饰的 UserManager ,也就是会反射调用 UserManager 的有参构造方法2021-10-03 20:37:33.697 INFO 13600 --- [
main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'userManager' with a different definition: replacing [Generic bean: class [com.lee.qsl.manager.UserManager]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [D:\qsl-project\spring-boot-bean-component\target\classes\com\lee\qsl\manager\UserManager.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=userConfig; factoryMethodName=userManager; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/lee/qsl/config/UserConfig.class]]
Spring 升级优化
Spring 5.1.2.RELEASE (Spring Boot 则是 2.1.0.RELEASE )做出了优化处理The bean 'userManager', defined in class path resource [com/lee/qsl/config/UserConfig.class], could not be registered. A bean with that name has already been defined in file [D:\qsl-project\spring-boot-bean-component\target\classes\com\lee\qsl\manager\UserManager.class] and overriding is disabled.
Spring 5.0.7.RELEASE 的区别allowBeanDefinitionOverriding 来控制是否允许 BeanDefinition 覆盖,默认情况下是不允许的spring.main.allow-bean-definition-overriding=true ,允许 BeanDefinition 覆盖总结
Spring 5.0.7.RELEASE ( Spring Boot 2.0.3.RELEASE ) 支持@Configuration + @Bean 与@Component 同时作用于同一个类@Configuration + @Bean 修饰的 BeanDefinition 覆盖掉@Component 修饰的 BeanDefinitionSpring 5.1.2.RELEASE 做出了优化处理allowBeanDefinitionOverriding ,将主动权交给了开发者,由开发者自己决定是否允许覆盖补充
allowBeanDefinitionOverriding ,前面讲的不对,后面特意去翻了下源码,补充如下DefaultListableBeanFactory 的时候就有了 private boolean allowBeanDefinitionOverriding = true;,默认是允许 BeanDefinition 覆盖isAllowBeanDefinitionOverriding()方法BeanDefinition 覆盖的,变的是 Spring Boot , Spring Boot 2.1.0 之前没有覆盖 Spring 的 allowBeanDefinitionOverriding 默认值,仍是允许 BeanDefinition 覆盖的allowBeanDefinitionOverridingallowBeanDefinitionOverriding 的默认值allowBeanDefinitionOverriding ,我想大家应该已经清楚了END
关注后端面试那些事,回复【2022面经】
获取最新大厂Java面经