上文讲了基于构造器进行依赖注入,这里讲解基于Setter方法进行注入。在Java世界中有个约定(Convention),那就是属性的设置和获取的方法名一般是:set+属性名(参数)及get+属性名()的方式。boolean类型稍有不同,可以使用is+属性名()方式来获取。

以下是一个示例。

MessageHandler.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MessageHandler {

    private MessageService messageService;

    public MessageService getMessageService() {
return messageService;
} public void setMessageService(MessageService messageService) {
this.messageService = messageService;
} public String handle() {
return messageService.sendService();
}
}

使用Setter方法注入如下所示。

1
2
3
4
<bean id="messageService" class="huangbowen.net.DependecyInjection.ConstructorInjection.SimpleMessageService"/>
<bean id="messageHandler" class="huangbowen.net.DependecyInjection.SetterInjection.MessageHandler">
<property name="messageService" ref="messageService"/>
</bean>

如果property的name为messageService,那么必须在类中有个叫做setMessageService的方法,这样才能完成注入。如果将MessageHandler.java中的setMessageService方法改为setMessageService1,那么注入就会失败,失败message如下所示。

1
2
3
4
5
6
7
...
java.lang.IllegalStateException: Failed to load ApplicationContext ...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageHandler' defined in class path resource [spring-context.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'messageService' of bean class [huangbowen.net.DependecyInjection.SetterInjection.MessageHandler]: Bean property 'messageService' is not writable or has an invalid setter method. Did you mean 'messageService1'? ...

当然可以同时使用构造器注入和setter方法注入。

Person.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Person {

    private String name;

    public Person(String name) {
this.name = name;
} private int age; public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getName() {
return name;
}
}

bean定义如下:

1
2
3
4
    <bean id="person" class="huangbowen.net.DependecyInjection.SetterInjection.Person">
<constructor-arg value="Tom"/>
<property name="age" value="20"/>
</bean>

要实现一个bean,即可以使用构造器注入,也可以使用setter注入,甚至可以在一个bean中综合使用这两种方式。那么在真正开发中应该作何取舍那?一般来说,使用构造器注入的依赖必须是强制的依赖,而使用setter注入的依赖则是可选的依赖。使用构造器注入生成的对象是完全初始化了的,用户可以直接拿来用,但是相比于setter方法而言用户也就失去了定制化的能力。如果你发现构造器参数过多,那么很可能说明该类承担的职责过多,应该从设计解耦的角度对类的职责进行拆分。使用setter注入的对象好处是,用户可以按需重新注入新的属性。

另外在进行依赖注入时,可以将某些属性抽出来成为一个元素,或者将元素内联成为一个属性。比如ref这个属性。

1
2
3
    <bean id="messageHandler" class="huangbowen.net.DependecyInjection.SetterInjection.MessageHandler">
<property name="messageService" ref="messageService" />
</bean>

它与以下xml配置完全等价。

1
2
3
4
5
 <bean id="messageHandler" class="huangbowen.net.DependecyInjection.SetterInjection.MessageHandler">
<property name="messageService">
<ref bean="messageService"/>
</property>
</bean>

value属性也可以独立为元素。

1
2
3
4
    <bean id="person" class="huangbowen.net.DependecyInjection.SetterInjection.Person">
<constructor-arg value="Tom"/>
<property name="age" value="20"/>
</bean>

其等价于:

1
2
3
4
5
6
    <bean id="person" class="huangbowen.net.DependecyInjection.SetterInjection.Person">
<constructor-arg value="Tom"/>
<property name="age">
<value>20</value>
</property>
</bean>

也可以显式指定value的类型。

1
2
3
4
5
6
    <bean id="person" class="huangbowen.net.DependecyInjection.SetterInjection.Person">
<constructor-arg value="Tom"/>
<property name="age">
<value type="int">20</value>
</property>
</bean>

比如有一个属性是个boolean值,如果想将其注入为true的话,不指定具体类型的话,Spring可能会将其作为字符串true对待。当然Spring会尝试将传入的字符串转换为setter方法希望的类型,但这种自动转换有时候并不是你期望的,这种情况下你就需要显式指定其类型。

本例中的源码请在我的GitHub上自行下载。

Spring-Context之六:基于Setter方法进行依赖注入的更多相关文章

  1. Spring基于Setter函数的依赖注入(DI)

    以下内容引用自http://wiki.jikexueyuan.com/project/spring/dependency-injection/spring-setter-based-dependenc ...

  2. Spring 基于set方法的依赖注入

    注意,再次强调,注入一个值用value,注入一个引用,要使用    ref   来注入 同时,注入的对象,要有set和get方法,才能通过方法注入. <?xml version="1. ...

  3. 三大框架 之 Spring(IOC控制反转、DI依赖注入)

    目录 常用词汇 left join与left outer join的区别 Struts2的标签库导入 Spring Spring概述 什么是Spring spring特点 下载 IOC 什么IOC 传 ...

  4. Spring详解(三)------DI依赖注入

    上一篇博客我们主要讲解了IOC控制反转,也就是说IOC 让程序员不在关注怎么去创建对象,而是关注与对象创建之后的操作,把对象的创建.初始化.销毁等工作交给spring容器来做.那么创建对象的时候,有可 ...

  5. Spring_01 spring容器、控制反转(IOC)、依赖注入(DI)

    目录 1 什么是spring框架 2 spring框架的特点 3 spring容器 3.1 什么是spring容器 3.2 spring容器创建对象的编程步骤 3.4 spring容器创建对象的方式 ...

  6. Spring IOC源代码具体解释之容器依赖注入

    Spring IOC源代码具体解释之容器依赖注入 上一篇博客中介绍了IOC容器的初始化.通过源代码分析大致了解了IOC容器初始化的一些知识.先简单回想下上篇的内容 加载bean定义文件的过程.这个过程 ...

  7. Spring升级案例之IOC介绍和依赖注入

    Spring升级案例之IOC介绍和依赖注入 一.IOC的概念和作用 1.什么是IOC 控制反转(Inversion of Control, IoC)是一种设计思想,在Java中就是将设计好的对象交给容 ...

  8. spring 配置bean的方法及依赖注入发方式

    Bean 的配置方式:通过全类名(反射).通过工厂方法(静态工厂方法 & 实例工厂方法).FactoryBean 这里依据全类名配置bean <bean id="helloWo ...

  9. 基于反射的通过set方法的依赖注入,可以看成一种设计模式,自己来用

    非常好用,在properties文件中配置字符串和类名之间的对应,在程序里读取文件,找到类名,通过反射,达到调用set方法的目的,然后直接将自己的指向其他类的对象的引用赋值,指向实体对象. 比如use ...

随机推荐

  1. 解压版MySQL5.7.1x的安装与配置

    解压版MySQL5.7.1x的安装与配置 MySQL安装文件分为两种,一种是msi格式的,一种是zip格式的.如果是msi格式的可以直接点击安装,按照它给出的安装提示进行安装(相信大家的英文可以看懂英 ...

  2. jquery制作弹出层带遮罩效果,点击阴影部分层消失

    jquery制作弹出层带遮罩效果,点击阴影部分层消失. 整体还是比较简单的. HTML代码很简单 <a href="#" class="big-link" ...

  3. phpStudy 的Apache虚拟主机配置

    放弃了wamp,朋友介绍了phpstudy,不错的一款软件,关键是能自由切换php版本.相关的阿帕奇虚拟主机配置参考:http://www.th7.cn/system/win/201506/10846 ...

  4. jquery easyui的treegrid的控制

    其中列的formatter很有作用,可以得到你想要的任何内容: 例: <table class="easyui-treegrid" id="tg" dat ...

  5. javascript鸭式辩型法实现接口

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  6. SAS 画折线图PROC GPLOT

    虽然最后做成PPT里的图表会被要求用EXCEL画,但当我们只是在分析的过程中,想看看数据的走势,直接在SAS里画会比EXCEL画便捷的多. 修改起来也会更加的简单,,不用不断的修改程序然后刷新EXCE ...

  7. xshell传输文件到Centos

    Reference: [1] http://www.myhack58.com/Article/sort099/sort0102/2015/61154.htm [2] http://www.cnblog ...

  8. Sql Servicer 复习笔记(1) 存储过程分布

    第一步:创建表 declare @countInt int declare @age int ) begin ),@countInt), @age,'中国北京') ; ; ) begin ; end ...

  9. java类集开发中一对多和多对多的关系的实现

    摘自<java开发实战经典>李兴华.著 一对多的关系 一个学校可以包含多个学生,一个学生属于一个学校,那么这就是一个典型的一对多关系,此时就可以通过类集进行关系的表示. 在定义Studen ...

  10. linux添加新LUN,无需重启

    linux添加新LUN,无需重启 在给存储增加新的Lun时,在linux下一般是: A.重启操作系统B.重启HBA卡驱动 1. kudzu添加完新硬盘后,运行命令kudzu重新扫描新的硬件设备,类似a ...