Spring 源码探秘:当 XML 撞上 JavaConfig,谁才是真正的赢家?
·
一、目的
验证当多个配置源(XML 与 Java Config) 定义同名Bean时:
- Spring的默认处理优先级。
- 冲突发生时,BeanDefination是属性合并还是完全替换。
- allowBeanDefinitionOverriding参数对容器启动的影响。
二、核心代码
提前准备:创建spring项目,引入spring-context依赖。
- 创建一个简单的Bean类
package com.exercise.exp1;
public class TestBean {
private String source;
//构造函数
public void setSource(String source) {this.source = source;}
public void printSource() {
System.out.println("I am from " + source);
}
// 用于验证XML的init-method 是否生效
public void xmlInit(){
System.out.println("XML定义的初始化方法被调用了");
}
}
- 准备xml配置文件(beans.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
实验核心:
1. id 必须与 JavaConfig 中的方法名(testBean)保持一致,才能触发冲突。
2. 设置 init-method 用于验证“图纸”是否被整体替换。
-->
<bean id="testBean" class="com.exercise.exp1.TestBean" init-method="xmlInit">
<property name="source" value="I am from XML" />
</bean>
</beans>
- 准备Java配置类(AppConfig.java)
package com.exercise.exp1;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
@Configuration
@ImportResource("classpath:beans.xml") // 引入xml
public class AppConfig {
@Bean
public TestBean testBean(){
TestBean bean = new TestBean();
bean.setSource("I am from JavaConfig");
return bean;
}
}
注意:
application.properties 里面添加以下代码:
# 允许同名 Bean 覆盖,这是观察“撕图纸”现象的前提
spring.main.allow-bean-definition-overriding=true
三、观察结果
当AppConfig.java中加上@ImportResource 时,结果:
注释掉时,结果:
四、结果说明
为什么注解的IoC会被xml的覆盖呢?
“ 加载顺序决定优先级 ”
因为Spring Boot的解析逻辑时:先处理主类的注解,然后再解析导入的资源。 XML 的 BeanDefinition 注册得更晚,它直接把之前 Java 定义的“图纸”给覆盖了。所以我看到了 XML 的初始化方法执行了,值也变成了 XML 的。
更多推荐




所有评论(0)