1. 简介
本教程将介绍如何在Spring框架中使用XML配置实现基础的依赖注入。虽然现在注解配置更流行,但理解XML配置对维护老项目或特定场景依然重要。
2. 依赖注入核心概念
依赖注入(Dependency Injection)是一种设计模式,对象的依赖由外部容器提供,而非自身创建。来看个典型场景:
假设有个应用类依赖业务逻辑服务:
public class IndexApp {
private IService service;
// 标准构造器/getter/setter
}
其中IService
是个接口:
public interface IService {
public String serve();
}
这个接口可能有多种实现,比如:
public class IndexService implements IService {
@Override
public String serve() {
return "Hello World";
}
}
这里IndexApp
作为高层组件,依赖低层组件IService
。这种设计实现了关键解耦:
- ✅ 高层模块不依赖低层模块细节
- ✅ 易于切换不同实现(如测试时用Mock对象)
- ✅ 符合开闭原则
3. 依赖注入实战
3.1. 通过属性注入
XML配置中通过setter方法注入依赖:
<bean
id="indexService"
class="com.baeldung.di.spring.IndexService" />
<bean
id="indexApp"
class="com.baeldung.di.spring.IndexApp" >
<property name="service" ref="indexService" />
</bean>
关键点说明:
id="indexService"
:定义bean的唯一标识ref="indexService"
:引用已定义的bean- 默认情况下bean是单例模式
- 实际调用的是
setService()
方法
⚠️ 注意:属性注入要求类必须有对应的setter方法,否则启动会报错
3.2. 通过构造函数注入
更推荐的方式是使用构造函数注入:
<bean
id="indexApp"
class="com.baeldung.di.spring.IndexApp">
<constructor-arg ref="indexService" />
</bean>
优势对比:
- ✅ 依赖关系在构造时确定,避免空指针
- ✅ 对象创建后即处于完整状态
- ✅ 便于单元测试(无需反射设置私有属性)
- ❌ 需要维护构造函数参数顺序
3.3. 静态工厂方法注入
当需要通过工厂创建对象时,可使用静态工厂方法:
public class StaticServiceFactory {
public static IService getNumber(int number) {
// 根据number返回不同实现
}
}
XML配置:
<bean id="messageService"
class="com.baeldung.di.spring.StaticServiceFactory"
factory-method="getService">
<constructor-arg value="1" />
</bean>
<bean id="indexApp" class="com.baeldung.di.spring.IndexApp">
<property name="service" ref="messageService" />
</bean>
关键配置:
factory-method="getService"
:指定静态工厂方法<constructor-arg>
:传递工厂方法参数
3.4. 实例工厂方法注入
对于非静态工厂方法:
public class InstanceServiceFactory {
public IService getNumber(int number) {
// 根据number返回不同实现
}
}
XML配置:
<bean id="indexServiceFactory"
class="com.baeldung.di.spring.InstanceServiceFactory" />
<bean id="messageService"
class="com.baeldung.di.spring.InstanceServiceFactory"
factory-method="getService" factory-bean="indexServiceFactory">
<constructor-arg value="1" />
</bean>
<bean id="indexApp" class="com.baeldung.di.spring.IndexApp">
<property name="service" ref="messageService" />
</bean>
与静态工厂的区别:
- 需要先创建工厂实例(
indexServiceFactory
) - 通过
factory-bean
指定工厂实例 - 适用于需要维护状态的工厂类
4. 测试验证
获取配置bean的测试代码:
@Test
public void whenGetBeans_returnsBean() {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
IndexApp indexApp = applicationContext.getBean("indexApp", IndexApp.class);
assertNotNull(indexApp);
assertEquals("Hello World", indexApp.getService().serve());
}
测试要点:
- 使用
ClassPathXmlApplicationContext
加载XML配置 - 通过
getBean()
获取实例 - 验证依赖是否正确注入
5. 总结
本文系统介绍了Spring中XML配置的四种依赖注入方式:
- 属性注入(setter方式)
- 构造函数注入
- 静态工厂方法注入
- 实例工厂方法注入
虽然现在注解配置更流行,但XML配置仍有其价值:
- ✅ 集中管理依赖关系
- ✅ 无需修改源码即可调整配置
- ✅ 适合大型项目的模块化管理
完整示例代码可在GitHub项目中获取,这是一个Maven项目,可直接导入运行。