Spring中的Setter依赖注入

时间:2020-01-09 10:44:29  来源:igfitidea点击:

在Spring的依赖注入后,我们已经介绍了依赖注入的概念,在这篇文章中,我们将详细介绍一种依赖注入的类型:Setter在Spring中的依赖注入。

对于另一种类型的依赖注入,构造函数依赖注入在Spring中检查此postConstructor依赖注入

Spring Setter依赖注入

在基于setter的DI中,Spring容器在调用无参数构造函数或者无参数静态工厂方法以实例化bean之后,在bean上调用setter方法。
为了配置基于setter的依赖关系,可以使用XML配置以及注释。我们将看到使用这两种方式进行操作的示例。

Spring Setter依赖注入示例

在该示例中,有一个用于下达订单的类,称为Order,可以从在线商店或者零售商店进行购买。在Order类中,使用setter依赖项注入来注入属性的依赖项。

public interface IStore {
	public void doPurchase(int items);
}
public class OnlineStore implements IStore {
  public void doPurchase(int items) {
    System.out.println("Doing online purchase of " + items + " Items");
  }
}
public class RetailStore implements IStore {
  public void doPurchase(int items) {
    System.out.println("Doing purchase of " + items + " Items from a brick and mortar store");
  }
}
public class Order {
  private IStore store;
  private int items;

  public void setStore(IStore store) {
    this.store = store;
  }
  public void setItems(int items) {
    this.items = items;
  }

  public void buyItems() {
    store.doPurchase(items);
  }
}

在Order类中,这是两个属性,一个是对Istore类型的引用,另一个是对int的引用。这些属性有setter方法,Spring容器将调用这些方法来设置配置的值。

如果我们使用的是XML配置,那么将按照以下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"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
  <!-- Store bean --> 
  <bean id="store" class="com.theitroad.SpringProject.RetailStore" />           
  <!-- Order bean with dependencies -->
  <bean id="orderBean" class="com.theitroad.SpringProject.Order">
    <property name="store" ref="store" />
    <property name="items" value="20" />
  </bean>
</beans>

为了提供setter依赖项,使用了<property>标签。

  • 当依赖关系是另一个bean时,使用" ref"属性。
  • 对于任何原始类型或者字符串,都使用"值"属性。

我们可以将以下类与main方法一起使用以读取配置并调用bean方法。

public class App {
  public static void main( String[] args ){
    // create context using configuration
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
    Order order = (Order) context.getBean("orderBean");
    order.buyItems();
    // close the context
    context.close();
  }
}

如果要使用注释在Spring中配置setter依赖项,则必须对类使用@Service或者@Component注释,以表明它们是Spring托管的组件,并且在完成组件扫描时会自动发现它们。

使用@autowired注释setter方法,以自动注入setter依赖项。

@Service
public class OnlineStore implements IStore {
  public void doPurchase(int items) {
    System.out.println("Doing online purchase of " + items + " Items");
  }
}
@Service
public class RetailStore implements IStore {
  public void doPurchase(int items) {
    System.out.println("Doing purchase of " + items + " Items from a brick and mortar store");
  }
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class Order {
  private IStore store;
  @Value("20")
  private int items;
  @Autowired
  @Qualifier("onlineStore")
  public void setStore(IStore store) {
    this.store = store;
  }
  public void buyItems() {
    store.doPurchase(items);
  }
}

由于存在两个类型为store的对象,因此已使用@Qualifier注释来告知必须连接哪个bean,否则将出现错误"没有可用的com.theitroad.SpringProject.IStore类型的合格bean"。

自动装配仅适用于引用,因此使用@Value注释提供原始值。

如果要使用XML设置组件扫描以自动发现Bean,则可以使用以下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"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
          
  <context:component-scan base-package="com.theitroad.SpringProject" />
</beans>

XML配置现在没有任何依赖性,只有<context:component-scan>标记。

基于构造函数或者基于setter的依赖项注入

根据Spring文档,基于构造器的DI优于基于设置器的DI。

"由于可以混合使用基于构造函数的DI和基于setter的DI,因此,将构造函数用于强制性依赖项,将setter方法或者配置方法用于可选性依赖项是一个很好的经验法则。

Spring团队通常提倡构造函数注入,因为它可以使应用程序组件实现为不可变对象,并确保所需的依赖项不为null。此外,注入构造函数的组件总是以完全初始化的状态返回到客户端(调用)代码。

Setter注入主要应仅用于可以在类中分配合理的默认值的可选依赖项。否则,必须在代码使用依赖项的任何地方执行非空检查。"