当前位置: 首页 > news >正文

html5网站源码下载坪地网站建设公司

html5网站源码下载,坪地网站建设公司,塘下建设银行网站,热门推广软件#x1f4e2;#x1f4e2;#x1f4e2;#x1f4e3;#x1f4e3;#x1f4e3; 哈喽#xff01;大家好#xff0c;我是「奇点」#xff0c;江湖人称 singularity。刚工作几年#xff0c;想和大家一同进步#x1f91d;#x1f91d; 一位上进心十足的【Java ToB端大厂… 哈喽大家好我是「奇点」江湖人称 singularity。刚工作几年想和大家一同进步 一位上进心十足的【Java ToB端大厂领域博主】 喜欢java和python平时比较懒能用程序解决的坚决不手动解决 ✨ 如果有对【java】感兴趣的【小可爱】欢迎关注我 ❤️❤️❤️感谢各位大可爱小可爱❤️❤️❤️ ———————————————— 如果觉得本文对你有帮助欢迎点赞欢迎关注我如果有补充欢迎评论交流我将努力创作更多更好的文章。 目录 前言 场景 1 两个同名 bean对应的两个实体类分别是同一个接口的不同实现 场景 2 两个同名 bean对应的两个类完全没有关系 总结 两个同名 bean均通过 xml 的 bean 标签声明 场景 3 两个同名 bean均通过 JavaConfig 的 Bean 注解声明 场景 4 两个同名 bean一个通过 xml 的 bean 标签声明一个通过 JavaConfig 的 Bean 注解声明。 场景 5 两个同名 bean均通过 xml 的 context:component-scan 标签扫描发现 bean。 场景 6 两个同名 bean均通过 Java Config 的注解 ComponentScan 扫描发现 bean 场景 7 两个同名 bean一个通过 xml 的 context:component-scan 标签扫描发现一个通过 Java Config 的注解 ComponentScan 扫描发现 场景 8 两个同名 bean一个通过 xml 的 bean 标签声明一个通过 xml 的 context:component-scan 标签扫描发现 场景 9 两个同名 bean一个通过 JavaConfig 的 Bean 注解声明一个通过 Java Config 的注解 ComponentScan 扫描发现。 场景梳理 前言 你是否遇到过以下问题 不同的类声明了同一个 bean 名字有时这两个类实现了同一个接口有时是完全无关的两个类。多个同名 bean有的在 xml 中声明有的以 Java Config 的方式声明。xml 文件中既配了 context:component-scan 标签扫描 bean又通过 bean 标签声明了 bean而且两种方式都可以取到同一个 bean。Java Config 方式既配了 ComponentScan 注解扫描 bean又通过注解 Bean 声明 bean而且两种方式都可以取到同一个 bean。xml 和 Java Config 两种方式混合使用两种方式都可以取到同一个 bean。 那么问题来了你清楚这几种场景下Spring 会分别执行什么策略吗也即最终取到的 bean 到底是哪一个 既然有这么多种场景那我们一一列举看看到底是怎样执行的背后的原理又是什么。 开始前先介绍一下环境 Spring Boot 2.x版本 我们用的启动类模板 package application;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.ImportResource;/*** 启动类模板程序可根据需要添加不同的注解以便引入对应的上下文。*/SpringBootApplication(exclude {DataSourceAutoConfiguration.class}) public class Applicationloader {public static void main(String[] args) {SpringApplication application new SpringApplication(Applicationloader.class);// Spring Boot版本2.1.0时默认不允许bean覆盖。我们为了研究bean覆盖机制将它改成允许覆盖。application.setAllowBeanDefinitionOverriding(true);// 启动运行并获取contextApplicationContext context application.run(args);// 获取bean并打印对应的实体类路径Object object context.getBean(myBean);System.out.println(object.getClass().getName());} } 场景 1 两个同名 bean对应的两个实体类分别是同一个接口的不同实现 场景描述两个同名 bean对应的两个实体类分别是同一个接口的不同实现。 package beans;public interface X { } package beans;import org.springframework.stereotype.Component;Component(value myBean) public class XImpl1 implements X { } package beans;import org.springframework.stereotype.Component;Component(value myBean) public class XImpl2 implements X { } 再定义 xml 配置文件 文件名applicationContext1.xml ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.2.xsdbean idmyBean classbeans.XImpl1/ /beans 文件名applicationContext2.xml  ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.2.xsdbean idmyBean classbeans.XImpl2/ /beans 启动类 package application;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.ImportResource;/*** 启动类模板程序可根据需要添加不同的注解以便引入对应的上下文。*/ImportResource({classpath:applicationContext1.xml, classpath:applicationContext2.xml}) SpringBootApplication(exclude {DataSourceAutoConfiguration.class}) public class Applicationloader {public static void main(String[] args) {...} } 执行结果 beans.XImpl2 如果对调两个 xml 文件的顺序 ImportResource({classpath:applicationContext2.xml, classpath:applicationContext1.xml}) 执行结果就会变成 beans.XImpl1 场景 2 两个同名 bean对应的两个类完全没有关系 场景描述两个同名 bean对应的两个类完全没有关系。 同样先定义 bean package beans;import org.springframework.stereotype.Component;Component(value myBean) public class Y { } package beans;import org.springframework.stereotype.Component;Component(value myBean) public class Z { }文件名applicationContext1.xml  ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.2.xsdbean idmyBean classbeans.Y//beans 文件名applicationContext2.xml ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.2.xsdbean idmyBean classbeans.Z//beans执行结果与场景 1 类似。 因此我们可以知道同名 bean 的覆盖与具体的类组织方式没有关系。 总结 两个同名 bean均通过 xml 的 bean 标签声明 场景描述两个同名 bean均通过 xml 的 bean 标签声明。其实这就是上面的场景了。 可以看出最终使用的是后面的 xml 中声明的 bean。其实原因是“后面的 xml 中声明的 bean”把“前面的 xml 中声明的 bean”覆盖了。我们可以看到 Bebug 信息 Overriding bean definition for bean myBean with a different definition: replacing [Generic bean: class [beans.Z]; scope; abstractfalse; lazyInitfalse; autowireMode0; dependencyCheck0; autowireCandidatetrue; primaryfalse; factoryBeanNamenull; factoryMethodNamenull; initMethodNamenull; destroyMethodNamenull; defined in class path resource [applicationContext2.xml]] with [Generic bean: class [beans.Y]; scope; abstractfalse; lazyInitfalse; autowireMode0; dependencyCheck0; autowireCandidatetrue; primaryfalse; factoryBeanNamenull; factoryMethodNamenull; initMethodNamenull; destroyMethodNamenull; defined in class path resource [applicationContext1.xml]] 这段信息位于源码 org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {...BeanDefinition existingDefinition this.beanDefinitionMap.get(beanName);if (existingDefinition ! null) {if (!isAllowBeanDefinitionOverriding()) {throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);}else if (existingDefinition.getRole() beanDefinition.getRole()) {...}else if (!beanDefinition.equals(existingDefinition)) {if (logger.isDebugEnabled()) {logger.debug(Overriding bean definition for bean beanName with a different definition: replacing [ existingDefinition ] with [ beanDefinition ]);}}else {...}this.beanDefinitionMap.put(beanName, beanDefinition);}else {...}if (existingDefinition ! null || containsSingleton(beanName)) {resetBeanDefinition(beanName);} } 可以看出这里首先判断了 allowBeanDefinitionOverriding 属性也即是否允许 bean 覆盖如果允许的话就继续判断 role、beanDefinition 等属性。当 debug 开启时就会打印出上述的信息告诉我们 bean 发生了覆盖行为。 如果我们把 ApplicationLoader 中的这行代码删除 application.setAllowBeanDefinitionOverriding(true); 由于 Spring Boot 2.1.0 及其以上版本默认不允许 bean 覆盖此时会直接抛 BeanDefinitionOverrideException 异常上面的源码也有体现。 如果是在 Spring Boot 2.1.0 以下默认是允许覆盖的但 setAllowBeanDefinitionOverriding 方法也不存在它是 2.1.0 加入的具体可以参见官方文档。 那我们如果想设置该属性该怎么办呢此时我们可以参考 Spring Boot2.1.0 的实现 org.springframework.boot.SpringApplication#prepareContext。通过方法 addInitializers 给 SpringApplication 注册 ApplicationContextInitializer并复写它的 initialize 方法通过入参 ConfigurableApplicationContext 获取 DefaultListableBeanFactory再调用 setAllowBeanDefinitionOverriding 进行设置。示例 首先自定义 MyAplicationInitializer package application;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext;public class MyAplicationInitializer implements ApplicationContextInitializer {Overridepublic void initialize(ConfigurableApplicationContext context) {ConfigurableListableBeanFactory beanFactory context.getBeanFactory();if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(false);}} } 然后注册自定义的 ApplicationInitializer SpringBootApplication(exclude {DataSourceAutoConfiguration.class}) public class Applicationloader {public static void main(String[] args) {application.addInitializers(new MyAplicationInitializer);...} } 这样就可以了。 另外网上还提到重定义 ContextLoader 的方式可以参考文末列出的第一篇文章。 场景 3 两个同名 bean均通过 JavaConfig 的 Bean 注解声明 场景描述两个同名 bean均通过 JavaConfig 的 Bean 注解声明。 bean 的定义不变我们增加一个配置类替换之前的 xml 配置文件 package configuration;import beans.Y; import beans.Z; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public class MyConfiguration {Bean(name myBean)public Object y() {return new Y();}Bean(name myBean)public Object z() {return new Z();} }package application;import configuration.MyConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Import;Import(MyConfiguration.class) SpringBootApplication(exclude {DataSourceAutoConfiguration.class}) public class Applicationloader {public static void main(String[] args) {...} } 结果 beans.Y 如果把配置文件中 Y 和 Z 的顺序对调也即将其改成这样 执行结果就会变成 beans.Z 可以看出最终使用的是位置靠前的 bean。其实原因是“后面的 bean”被忽略了 参考源码 org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod  private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {...// Has this effectively been overridden before (e.g. via XML)?if (isOverriddenByExistingDefinition(beanMethod, beanName)) {if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),beanName, Bean name derived from Bean method beanMethod.getMetadata().getMethodName() clashes with bean name for containing configuration class; please make those names unique!);}return;}... } 可知如果发现后加载的 bean 可以被 overridden就会将其忽略。因此最终使用的是先前被加载的 bean。 场景 4 两个同名 bean一个通过 xml 的 bean 标签声明一个通过 JavaConfig 的 Bean 注解声明。 场景描述两个同名 bean一个通过 xml 的 bean 标签声明一个通过 JavaConfig 的 Bean 注解声明。 我们通过 xml 声明 Y ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.2.xsdbean idmyBean classbeans.Y//beans 通过 JavaConfig 声明 Z package configuration;import beans.Z; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public class MyConfiguration {Bean(name myBean)public Object z() {return new Z();} } package application;import configuration.MyConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.ImportResource;ImportResource({classpath:applicationContext.xml}) Import(MyConfiguration.class) SpringBootApplication(exclude {DataSourceAutoConfiguration.class}) public class Applicationloader {public static void main(String[] args) {...} } beans.Y 交换导入的位置 Import(MyConfiguration.class) ImportResource({classpath:applicationContext.xml})两者的上下位置对调一下输出结果也不变。 因此可以得出结论当 xml 和 Java Config 均采用注解引入时最终拿到的 bean 是 xml 文件中声明的。原因是 xml 在 Java Config 之后加载把 Java Config 声明的 bean 覆盖了。此时我们可以看到 Debug 信息 Overriding bean definition for bean myBean with a different definition: replacing [Root bean: class [null]; scope; abstractfalse; lazyInitfalse; autowireMode3; dependencyCheck0; autowireCandidatetrue; primaryfalse; factoryBeanNameconfiguration.MyConfiguration; factoryMethodNamez; initMethodNamenull; destroyMethodName(inferred); defined in configuration.MyConfiguration] with [Generic bean: class [beans.Y]; scope; abstractfalse; lazyInitfalse; autowireMode0; dependencyCheck0; autowireCandidatetrue; primaryfalse; factoryBeanNamenull; factoryMethodNamenull; initMethodNamenull; destroyMethodNamenull; defined in class path resource [applicationContext.xml]] 场景 5 两个同名 bean均通过 xml 的 context:component-scan 标签扫描发现 bean。 场景描述两个同名 bean均通过 xml 的 context:component-scan 标签扫描发现 bean。 applicationContext.xml 文件 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.2.xsdcontext:component-scan base-packagebeans//beans 由于采用了扫描的方式我们不用写两个 xml 文件分别声明两个 bean 了现在一个 applicationContext.xml 文件就可以搞定。 package application;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.ImportResource;ImportResource({classpath:applicationContext.xml}) SpringBootApplication(exclude {DataSourceAutoConfiguration.class}) public class Applicationloader {public static void main(String[] args) {...} } org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [applicationContext.xml]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name myBean for bean class [beans.Z] conflicts with existing, non-compatible bean definition of same name and class [beans.Y]at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:419) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:224) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:195) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.lambda$loadBeanDefinitionsFromImportedResources$0(ConfigurationClassBeanDefinitionReader.java:358) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[na:1.8.0_171]at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromImportedResources(ConfigurationClassBeanDefinitionReader.java:325) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:144) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:117) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:327) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:232) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:691) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:528) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]at application.Applicationloader.main(Applicationloader.java:23) [classes/:na] Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name myBean for bean class [beans.Z] conflicts with existing, non-compatible bean definition of same name and class [beans.Y]at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:348) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:286) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(ComponentScanBeanDefinitionParser.java:90) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at 可以看到抛了异常异常信息告诉我们发现了两个 bean但它们不兼容。抛异常的源码位于 org.springframework.context.annotation.ClassPathBeanDefinitionScanner#checkCandidate protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {if (!this.registry.containsBeanDefinition(beanName)) {return true;}BeanDefinition existingDef this.registry.getBeanDefinition(beanName);BeanDefinition originatingDef existingDef.getOriginatingBeanDefinition();if (originatingDef ! null) {existingDef originatingDef;}if (isCompatible(beanDefinition, existingDef)) {return false;}throw new ConflictingBeanDefinitionException(Annotation-specified bean name beanName for bean class [ beanDefinition.getBeanClassName() ] conflicts with existing, non-compatible bean definition of same name and class [ existingDef.getBeanClassName() ]); } 这段代码执行时机很早要知道我们现在是允许同名 bean 覆盖的但显然可以看出还没有走到判断 allowBeanDefinitionOverriding 属性的地方扫描出来就检查候选 bean发现有两个同名 bean直接报冲突。 场景 6 两个同名 bean均通过 Java Config 的注解 ComponentScan 扫描发现 bean 场景描述两个同名 bean均通过 Java Config 的注解 ComponentScan 扫描发现 bean。 package configuration;import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;ComponentScan(basePackages beans) Configuration public class MyConfiguration {Bean(name myBean)public Object y() {return new Y();}Bean(name myBean)public Object z() {return new Z();} } org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [application.Applicationloader]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name myBean for bean class [beans.Z] conflicts with existing, non-compatible bean definition of same name and class [beans.Y]at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:599) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:302) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:242) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:199) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:167) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:315) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:232) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:691) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:528) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]at application.Applicationloader.main(Applicationloader.java:23) [classes/:na] Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name myBean for bean class [beans.Z] conflicts with existing, non-compatible bean definition of same name and class [beans.Y]at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:348) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:286) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:287) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:242) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:589) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]... 15 common frames omitted 可以看到抛了异常异常信息告诉我们发现了两个 bean但它们不兼容。 同时我们可以看到场景 5和 6 类似抛的异常相同。但由于场景 5 是 xml 解析场景 6 是 Java Config 解析因此具体的堆栈信息有些差异。 场景 7 两个同名 bean一个通过 xml 的 context:component-scan 标签扫描发现一个通过 Java Config 的注解 ComponentScan 扫描发现 场景描述两个同名 bean一个通过 xml 的 context:component-scan 标签扫描发现一个通过 Java Config 的注解 ComponentScan 扫描发现。 文件名applicationContext.xml  通过 xml 扫描 Y ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.2.xsdcontext:component-scan base-packagebeans use-default-filtersfalsecontext:include-filter typeassignable expressionbeans.Y//context:component-scan/beans 通过 JavaConfig 扫描 Z package configuration;import beans.Z; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType;ComponentScan(basePackages beans,includeFilters ComponentScan.Filter(type FilterType.ASSIGNABLE_TYPE, classes Z.class), useDefaultFilters false) Configuration public class MyConfiguration { } ImportResource({classpath:applicationContext.xml}) Import(MyConfiguration.class) SpringBootApplication(exclude {DataSourceAutoConfiguration.class}) public class Applicationloader {public static void main(String[] args) {...} } org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [applicationContext.xml]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name myBean for bean class [beans.Y] conflicts with existing, non-compatible bean definition of same name and class [beans.Z]at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:419) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:224) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:195) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.lambda$loadBeanDefinitionsFromImportedResources$0(ConfigurationClassBeanDefinitionReader.java:358) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[na:1.8.0_171]at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromImportedResources(ConfigurationClassBeanDefinitionReader.java:325) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:144) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:117) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:327) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:232) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:691) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:528) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]at application.Applicationloader.main(Applicationloader.java:25) [classes/:na] Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name myBean for bean class [beans.Y] conflicts with existing, non-compatible bean definition of same name and class [beans.Z]at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:348) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:286) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(ComponentScanBeanDefinitionParser.java:90) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:74) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1366) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1352) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:179) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:149) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:96) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:513) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:393) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]... 21 common frames omitted 发现抛异常异常信息和场景 5 一致都是在 xml 解析过程中抛的异常。 交换位置 Import(MyConfiguration.class) ImportResource({classpath:applicationContext.xml}) SpringBootApplication(exclude {DataSourceAutoConfiguration.class}) public class Applicationloader {public static void main(String[] args) {...} } 再次执行。发现和上面抛的异常一致。 因此我们可以得出结论当 xml 和 Java Config 都扫描 bean 时注解 ComponentScan 会先于 xml 标签中的 context:component-scan 标签执行因为抛异常的点在解析后者的过程中也可以调试源码得出相同的结论参见下图。 场景 8 两个同名 bean一个通过 xml 的 bean 标签声明一个通过 xml 的 context:component-scan 标签扫描发现 场景描述两个同名 bean一个通过 xml 的 bean 标签声明一个通过 xml 的 context:component-scan 标签扫描发现。 我们通过 xml 的 bean 标签声明 Y并通过 xml 的 context:component-scan 标签扫描发现 Z ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.2.xsdbean idmyBean classbeans.Y/context:component-scan base-packagebeans use-default-filtersfalsecontext:include-filter typeassignable expressionbeans.Z//context:component-scan/beans ImportResource({classpath:applicationContext.xml}) SpringBootApplication(exclude {DataSourceAutoConfiguration.class}) public class Applicationloader {public static void main(String[] args) {...} } 结果 beans.Y 如果我们通过 xml 的 bean 标签声明 Z并通过 xml 的 context:component-scan 标签扫描发现 Y 的话执行结果就会是 beans.Z 可以看出最终使用的是通过 xml 的 bean 标签声明的 bean而非通过 xml 的 context:component-scan 标签扫描发现的 bean。 我们跟踪源码会发现在注册 bean 前会在 org.springframework.context.annotation.ClassPathBeanDefinitionScanner#checkCandidate 方法中判断两个 bean 是否兼容第 21 行代码如果兼容的话会返回 falsebean 就不会被注册了注意这里的解析顺序是先解析通过 xml 的 bean 标签声明的 bean后解析通过 xml 的 context:component-scan 标签扫描发现的 bean稍后解释 /*** Check the given candidates bean name, determining whether the corresponding* bean definition needs to be registered or conflicts with an existing definition.* param beanName the suggested name for the bean* param beanDefinition the corresponding bean definition* return {code true} if the bean can be registered as-is;* {code false} if it should be skipped because there is an* existing, compatible bean definition for the specified name* throws ConflictingBeanDefinitionException if an existing, incompatible* bean definition has been found for the specified name*/ protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {if (!this.registry.containsBeanDefinition(beanName)) {return true;}BeanDefinition existingDef this.registry.getBeanDefinition(beanName);BeanDefinition originatingDef existingDef.getOriginatingBeanDefinition();if (originatingDef ! null) {existingDef originatingDef;}if (isCompatible(beanDefinition, existingDef)) {return false;}throw new ConflictingBeanDefinitionException(Annotation-specified bean name beanName for bean class [ beanDefinition.getBeanClassName() ] conflicts with existing, non-compatible bean definition of same name and class [ existingDef.getBeanClassName() ]); } 具体地org.springframework.context.annotation.ClassPathBeanDefinitionScanner#isCompatible /*** Determine whether the given new bean definition is compatible with* the given existing bean definition.* pThe default implementation considers them as compatible when the existing* bean definition comes from the same source or from a non-scanning source.* param newDefinition the new bean definition, originated from scanning* param existingDefinition the existing bean definition, potentially an* explicitly defined one or a previously generated one from scanning* return whether the definitions are considered as compatible, with the* new definition to be skipped in favor of the existing definition*/ protected boolean isCompatible(BeanDefinition newDefinition, BeanDefinition existingDefinition) {return (!(existingDefinition instanceof ScannedGenericBeanDefinition) || // explicitly registered overriding bean(newDefinition.getSource() ! null newDefinition.getSource().equals(existingDefinition.getSource())) || // scanned same file twicenewDefinition.equals(existingDefinition)); // scanned equivalent class twice } 我们知道先前解析的 bean 是通过 xml 的 bean 标签声明的因此 existingDefinition 的类型是 org.springframework.beans.factory.support.GenericBeanDefinition因此条件 !(existingDefinition instanceof ScannedGenericBeanDefinition) 为 true也就表示兼容因此该方法返回 true。附注回顾一下场景 5、6、7它们就是在方法 checkCandidate 中抛了异常因为这 3 个场景中的两个 bean 都是扫描发现的因此 existingDefinition 的类型是 ScannedGenericBeanDefinition会被判定为不兼容。 最终会导致通过 xml 的 context:component-scan 标签扫描发现的 bean 未被注册。因此我们最终使用的是通过 xml 的 bean 标签声明的 bean。 前面留了个小尾巴解析顺序是先解析通过 xml 的 bean 标签声明的 bean后解析通过 xml 的 context:component-scan 标签扫描发现的 bean。源码位于 org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions /*** Parse the elements at the root level in the document:* import, alias, bean.* param root the DOM root element of the document*/ protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {if (delegate.isDefaultNamespace(root)) {NodeList nl root.getChildNodes();for (int i 0; i nl.getLength(); i) {Node node nl.item(i);if (node instanceof Element) {Element ele (Element) node;if (delegate.isDefaultNamespace(ele)) {parseDefaultElement(ele, delegate);}else {delegate.parseCustomElement(ele);}}}}else {delegate.parseCustomElement(root);} } 注意parseDefaultElement(ele, delegate);和delegate.parseCustomElement(ele); parseDefaultElement用于解析默认命名空间的标签 delegate.parseCustomElement用于解析自定义命名空间的标签。 bean 标签属于默认命名空间而 component-scan 属于自定义的命名空间。明显可以看出先解析通过 xml 的 bean 标签声明的 bean后解析通过 xml 的 context:component-scan 标签扫描发现的 bean。 场景 9 两个同名 bean一个通过 JavaConfig 的 Bean 注解声明一个通过 Java Config 的注解 ComponentScan 扫描发现。 场景描述两个同名 bean一个通过 JavaConfig 的 Bean 注解声明一个通过 Java Config 的注解 ComponentScan 扫描发现。 我们通过 JavaConfig 的 Bean 注解声明 Y并通过 Java Config 的注解 ComponentScan 扫描发现 Z ComponentScan(basePackages beans,includeFilters ComponentScan.Filter(type FilterType.ASSIGNABLE_TYPE, classes Z.class), useDefaultFilters false) Configuration public class MyConfiguration {Bean(name myBean)public Object y() {return new Y();} } Import(MyConfiguration.class) SpringBootApplication(exclude {DataSourceAutoConfiguration.class}) public class Applicationloader {public static void main(String[] args) {...} } 执行结果: beans.Y 如果把 Y 和 Z 的声明方式对调一下也即配置文件改成 ComponentScan(basePackages beans,includeFilters ComponentScan.Filter(type FilterType.ASSIGNABLE_TYPE, classes Y.class), useDefaultFilters false) Configuration public class MyConfiguration {Bean(name myBean)public Object z() {return new Z();} } 执行结果就是 beans.Z 可以看出最终使用的是通过注解 Bean 声明的 bean。通过源码可以看出“通过注解 ComponentScan 扫描的 bean”被“通过注解 Bean 声明的 bean”覆盖了源码位于 org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#isOverriddenByExistingDefinition protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) {...// A bean definition resulting from a component scan can be silently overridden// by an Bean method, as of 4.2...if (existingBeanDef instanceof ScannedGenericBeanDefinition) {return false;}... } 上面的代码明确说明通过 component scan 扫描的 bean 会被通过 Bean 声明的 bean 覆盖掉而且这种覆盖没有任何提示也即 silently悄悄地覆盖掉。 场景梳理 根据不同的维度我们梳理一下上面的场景方便对号入座 根据实体类区分这两种情况下的覆盖策略是相同的 同一个接口的两个实现对应的的两个 bean 同名。场景 1 两个同名 bean对应的两个类完全没有关系场景 2 根据配置方式区分 xml 方式场景 3 Java config 方式场景 3 xml 和 Java config 方式混用场景 4最终使用的是 xml 配置的 bean 根据 bean 发现方式区分通过 Bean 注解声明的 bean会将 ComponentScan 扫描的 bean 覆盖 xml 的 component-scan 扫描方式场景 5 Java Config 的 ComponentScan 扫描方式场景 6 xml 的 component-scan 扫描方式 和 Java Config 的 ComponentScan 扫描方式 混用场景 7 xml 的 bean 标签方式场景 3 Java Config 的 Bean 注解声明 bean场景 3 xml 的 component-scan 扫描方式 和 bean 标签方式混用场景 8 Java Config 的 ComponentScan 扫描方式 和 通过 Bean 注解声明 bean 混用场景 9 本文列举了平时开发中可能遇到的多种 bean 配置方式并且简析了相关源码解释了执行结果。 本文并未讲解 bean 解析整体流程因此强烈建议读者手动调试自己过一遍源码。 很多细节问题在方法源码注释标注了这些内容在 Spring 的官方文档也有说明。建议抽空看一下官方文档也许很多问题就迎刃而解了。 资源 Githubhttps://github.com/xiaoxi666/spring-demo/tree/bean_name该分支搭建好了 SpringBoot 环境并配置了 logback 日志。。 重定义 ContextLoader控制 isAllowBeanDefinitionOverridng 参数提到了父子容器
http://www.zqtcl.cn/news/847490/

相关文章:

  • 如何分析一个网站网站页面建设
  • 做网站好网页制作3个网页的网站图片
  • 合肥网站建设网站推广新的网站建设一般多少钱
  • 北京网站改版哪家好网站关键词怎样做优化
  • 网站开发行业分析wordpress 粘贴表格
  • 网站开发的招标参数网络科技公司网站源码下载
  • 属于网络营销站点推广的是seo好wordpress主题
  • j2ee只做网站阿里企业邮箱免费
  • 做企业网站需要买什么资料室内设计学徒
  • 网站新增关键词设计公司logo公司文化
  • 怎么写一个网站程序农产品网站如何做地推
  • 北京网站优化服务商有了域名怎么建网站
  • 转运网站开发国外永久免费crm系统
  • 免费网站建设网站wordpress扁平化中文主题
  • 外贸企业网站策划个人简历模板免费可编辑
  • 自助建站免费建站免费建站工具有哪些
  • 海外网站导航前端静态网站开发
  • 德庆网站建设价格网站的月度流量统计报告怎么做
  • 网站哪里买外链品牌网站设计步骤
  • 网站推广 优帮云淄博网站制作公司
  • 二手书哪个网站做的好wordpress 直排主题
  • 网站开发风险分析做情诗网站
  • 怎样可以快速增加网站的反链网络广告平台有哪些
  • 学校网站源码小游戏网站审核怎么做
  • 西乡网站建设政务网站开发协议
  • 美食网站开发环境北京app网站建设
  • 郑州网站建设推广渠道重庆网站建设公司下载
  • 宜宾营销型网站建设网站建设需要什么资质
  • 重庆建网站有哪些学跨境电商要多少钱
  • 上海建设钢结构工程网站深圳电器公司排名