依赖注入的作用:
使用Spring框架创建对象时,动态地将其所依赖的对象注入到Bean组件中,其实现主要有两种方式,一种是构造方法注入,另一种是属性setter方法注入。
1.构造方法注入
创建项目,在com.ssm.entity的包中,新建AdminInfo类,包括id、name、pwd三个属性,其中id属性使用setter方法注入,name和pwd属性使用构造方法注入,新建带两个参数的构造方法,代码如下:
package com.ssm.entity;
public class AdminInfo {
private int id;
private String name;
private String pwd;
public void setId(int id) {
this.id = id;
}
//省略原有getter/setter方法
public AdminInfo( String name, String pwd) {
this.name = name;
this.pwd = pwd;
}
public AdminInfo() {
}
public void print() {
System.out.println(id + "--" + name + "--" + pwd);
}
}
使用setter方法注入时,Spring通过JavaBean的无参构造方法实例化对象。
创建配置文件applicationContext.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--依赖注入的类型之构造注入-->
<bean id="adminInfo" class="com.ssm.entity.AdminInfo">
<property name="id" value="5"></property>
<constructor-arg name="name" value="admin"></constructor-arg>
<constructor-arg name="pwd" value="123456"></constructor-arg>
</bean>
</beans>
一个<constructor-arg>元素表示构造方法的一个参数,且使用时不区分顺序,当构造方法的参数出现混淆,无法区分时,可通过<constructor-arg>元素的index属性指定该参数的位置索引,索引从0开始。<constructor-arg>元素还提供了type属性用来指定参数的类型,避免字符串和基本数据类型的混淆。
新建测试类TestSpringConstructor,代码如下:
package com.ssm;
import com.ssm.entity.AdminInfo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 测试构造方法注入
*/
public class TestSpringConstructor {
public static void main(String[] args) {
//加载applicationContext.xml配置
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取配置中的adminInfo实例
AdminInfo adminInfo = (AdminInfo)ctx.getBean("adminInfo");
adminInfo.print();
}
}
运行测试类,控制台的运行结果输出为“5--admin-123456”,通过调用AdminInfo类中的print()方法,打印输出AdminInfo类中的属性值,属性值通过在applicationContext.xml的配置文件中注入实现。
2.属性setter方法注入
属性setter方法注入是指Spring容器使用setter方法注入被依赖的值或对象,是常见的一种依赖注入方式,这种注入方式具有高度灵活性。
使用p命名空间来简化属性的注入,使用前先添加p命名空间的声明,配置文件中的关键代码如下:
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--使用p命名空间法注入值-属性setter方法注入-->
<bean id="admin" class="com.ssm.entity.AdminInfo" p:id="8" p:name="admin" p:pwd="admin"/>
</beans>
为AdminInfo类中的name和pwd属性添加相应的setter方法,并创建测试类,测试类代码如下:
package com.ssm;
import com.ssm.entity.AdminInfo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 测试构造方法注入
*/
public class TestSpringConstructor {
public static void main(String[] args) {
//加载applicationContext.xml配置
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取配置中的admin实例
AdminInfo adminInfo = (AdminInfo)ctx.getBean("admin");
adminInfo.print();
}
}
运行测试类,控制台的运行结果为“8--admin--admin“,使用p命名空间简化配置的效果很明显,其使用方式总结如下:
- 对于直接量(基本数据类型,字符串)属性,使用方式如下:p:属性名="属性值"。
- 对于引用Bean的属性,使用方式如下:p:属性名-ref="Bean的id"。
3.两种注入方式的对比
构造方法注入和属性setter方法注入两种方式,它们各有优缺点,两种方式的特点总结如下:
-
使用setter方法时,与传统的JavaBean写法很类似,程序开发人员更容易了解和接受,通过setter方法设定依赖关系显得更加直观、自然。
-
对于就复杂的依赖关系,如果采用构造方法注入,会导致构造器过于臃肿,难以阅读。尤其是在某些属性可选的情况下,多参数的构造器更加笨重。
-
构造方法注入可以在构造器中决定依赖关系的注入顺序,当某些属性的赋值操作有先后顺序时,这点尤为重要。
-
对于依赖关系无须变化的Bean,构造方法注入更有用处。如果没有setter方法,所有的依赖关系全部在构造器内设定,后续代码不会对依赖关系产生破坏。依赖关系只能在构造器中设定,所以只有组件的创建者才能改变组件的依赖关系。而对组件的调用者而言,组件内部的依赖关系完全透明,更符合高内聚的原则。