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

