1.简介

在本文中,我们将学习如何使用Spring Framework完成基于XML的简单bean配置。

2. 依赖

让我们从在pom.xml中添加Spring的依赖开始:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.1.9.RELEASE</version>
</dependency>

Spring依赖的最新版本可以在这里找到。

3.依赖注入

依赖注入是一种通过外部容器提供对象的依赖关系的技术。

假设我们有一个依赖于实际上处理业务逻辑的服务的程序类:

public class IndexApp {
    private IService service;
    // constructors/getters/setters
}

然后,IService是一个接口:

public interface IService {
    public String serve();
}

该接口可以有多种实现。

下面的代码是一个潜在的实现:

public class IndexService implements IService {
    @Override
    public String serve() {
        return "Hello ripjava.com";
    }
}

在这里,IndexApp是一个高级组件,它依赖于称为IService的低级组件。

我们创建接口的目的,本质上,我将IndexAppIService的特定实现脱钩,该实现可能会因各种因素而有所不同。

4. 快速上手

让我们看看如何注入依赖。

4.1 使用属性

让我们看看如何使用基于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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="indexService"
            class="com.ripjava.xmlbase.IndexService"/>
    
    <bean id="indexApp"
          class="com.ripjava.xmlbase.IndexApp">
        <property name="service" ref="indexService"/>
    </bean>

</beans>

可以看出,我们创建了IndexService的实例并为其分配一个ID。默认情况下,bean是单例。

另外,我们创建了IndexApp的实例,并使用setter方法注入另一个bean。

我们来测试一下:

@Test
public void test_DIBySetter() {
  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-xml-base-di.xml");
  IndexApp indexApp = applicationContext.getBean("indexApp", IndexApp.class);
  assertNotNull(indexApp);
}

4.2 使用构造函数

如果不用想通过setter方法注入bean,我们可以使用构造函数注入依赖项:

<bean id="indexApp2"
      class="com.ripjava.xmlbase.IndexApp">
  <constructor-arg ref="indexService" />
</bean>

我们来测试一下:

@Test
public void test_DIByConstructor() {
  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-xml-base-di.xml");
  IndexApp indexApp = applicationContext.getBean("indexApp2", IndexApp.class);
  assertNotNull(indexApp);
}

4.3 使用静态工厂

我们还可以通过静态工厂返回的bean来进行注入。

让我们创建一个简单的工厂,该工厂根据数字返回IService的实例:

public class StaticServiceFactory {
    public static IService getService(int number) {
        switch (number) {
            case 1:
                return new IndexService();
            default:
                throw new IllegalArgumentException("Unknown parameter " + number);
        }
    }
}

现在,让我们看看如何使用上述实现通过基于XML的配置将bean注入IndexApp3

<bean id="indexService3" class="com.ripjava.xmlbase.StaticServiceFactory" factory-method="getService">
  <constructor-arg value="1" />
</bean>
<bean id="indexApp3"
      class="com.ripjava.xmlbase.IndexApp">
  <property name="service" ref="indexService3"/>
</bean>

在上面的示例中,我们使用factory-method调用静态方法getService 来创建一个ID为indexService3的bean,并将其注入IndexApp3中。

我们来测试一下:

@Test
public void test_DIByStaticFactory() {
  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-xml-base-di.xml");
  IndexApp indexApp = applicationContext.getBean("indexApp3", IndexApp.class);
  assertNotNull(indexApp);
}

4.4 使用工厂方法

让我们创建一个实例工厂,该工厂根据提供的数字返回IService的实例。

这次,该方法不是静态的:

public class InstanceServiceFactory {
    public IService getService(int number) {
        switch (number) {
            case 1:
                return new IndexService();
            default:
                throw new IllegalArgumentException("Unknown parameter " + number);
        }
    }
}

现在让我们看看如何使用上述实现通过XML配置将bean注入IndexApp4

<bean id="indexServiceFactory"
      class="com.ripjava.xmlbase.InstanceServiceFactory" />
<bean id="indexService4"
      class="com.ripjava.xmlbase.InstanceServiceFactory"
      factory-method="getService" factory-bean="indexServiceFactory">
  <constructor-arg value="1" />
</bean>
<bean id="indexApp4" class="com.ripjava.xmlbase.IndexApp">
  <property name="service" ref="indexService4" />
</bean>

在上面的示例中,我们使用factory-methodInstanceServiceFactory实例上调用getService方法,以创建一个ID为indexService4的bean,并将其注入IndexApp4中。

我们来测试一下:

@Test
public void test_DIByFactoryMethod() {
  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-xml-base-di.xml");
  IndexApp indexApp = applicationContext.getBean("indexApp4", IndexApp.class);
  assertNotNull(indexApp);
}

5. 总结

在本文中,我们举例说明了如何在Spring Framework使用基于XML的配置来注入依赖项。

最后,往常一样,代码可以在Github上找到。