文章目录
上一节讲述了如何在XML中定义bean。这些bean都比较简单,基本只是个单一对象。但是在企业级开发中,一个对象或多或少都要跟其他对象发生关联,比如继承、调用、实现接口等。传统的方法中,如果对象A某方法的实现要调用对象B的方法,那么一般由对象A来维护对象B的生命周期,包括创建、调用、销毁等。而引入了控制反转(即依赖注入)以后,对象A只管负责对对象B的调用,对象B的整个声明周期都交由IoC容器管理。甚至对象A在实现时基于接口实现,IoC容器可以按需注入实现了指定接口的对象到对象A中,这样无需修改任何代码就可以灵活的实现需求变动。
Spring中对bean的依赖注入主要有两种方式,一种是基于构造器注入,一种是基于Setter方法注入。
以下是构造方法注入的一个简单例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public class MessageHandler {
private MessageService messageService;
public MessageHandler(MessageService messageService) { this.messageService = messageService; }
public String handle() { return messageService.sendService(); } }
|
1 2 3 4 5 6 7
| <bean id="messageService" class="huangbowen.net.DependecyInjection.ConstructorInjection.SimpleMessageService"/>
<bean id="messageHandler" class="huangbowen.net.DependecyInjection.ConstructorInjection.MessageHandler"> <constructor-arg ref="messageService"/> </bean>
|
这里的java对象是POJO(plain old java object)的,说明了Spring框架是无侵入性的。在xml中通过constructor-arg属性来向MessageHandler注入对象,ref指向了另一个bean。
由于该构造函数只有一个参数,所以无需指明注入的是哪个参数。
如果构造函数有多个参数,那么有很多方式可以指定注入的对象与参数的对应关系。
可以通过索引来指定。
1 2 3 4 5 6
| <bean id="person" class="huangbowen.net.DependecyInjection.ConstructorInjection.Person"> <constructor-arg index="0" value="Tom"/> <constructor-arg index="1" value="20"/> </bean>
|
也可以通过类型来指定。
1 2 3 4 5 6
| <bean id="person" class="huangbowen.net.DependecyInjection.ConstructorInjection.Person"> <constructor-arg type="java.lang.String" value="Tom"/> <constructor-arg type="int" value="20"/> </bean>
|
这要求两个类型不能一样或者不能有继承关系,要不然Spring就不知道映射关系了。如果出现了这样的情况,就需要借助其它的方式来告诉Spring你的参数映射关系。
也可以通过参数名来指定。
1 2 3 4 5 6
| <bean id="person" class="huangbowen.net.DependecyInjection.ConstructorInjection.Person"> <constructor-arg name="name" value="Tom"/> <constructor-arg name="age" value="20"/> </bean>
|
这种注入方法有个风险就是如果你的源代码在编译时关闭了debug标志,那么Spring就无法获取构造器的参数名了。不过可以使用@ConstructorProperties 属性显式指定构造器参数名称。
Person.java1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
public class Person { private String name; private int age;
@ConstructorProperties({"name", "age"}) public Person(String name, int age) { this.name = name; this.age = age; } }
|
本例中的源码请在我的GitHub上自行下载。