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>    

关键点说明:

  1. id="indexService":定义bean的唯一标识
  2. ref="indexService":引用已定义的bean
  3. 默认情况下bean是单例模式
  4. 实际调用的是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());
}

测试要点:

  1. 使用ClassPathXmlApplicationContext加载XML配置
  2. 通过getBean()获取实例
  3. 验证依赖是否正确注入

5. 总结

本文系统介绍了Spring中XML配置的四种依赖注入方式:

  1. 属性注入(setter方式)
  2. 构造函数注入
  3. 静态工厂方法注入
  4. 实例工厂方法注入

虽然现在注解配置更流行,但XML配置仍有其价值:

  • ✅ 集中管理依赖关系
  • ✅ 无需修改源码即可调整配置
  • ✅ 适合大型项目的模块化管理

完整示例代码可在GitHub项目中获取,这是一个Maven项目,可直接导入运行。