SpringDI依赖注入

Posted brent

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringDI依赖注入相关的知识,希望对你有一定的参考价值。

两种注入方式

DI(Dependency Injection)依赖注入 。

依赖注入,即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。

所谓的依赖注入其实就是,在创建对象的同时或之后,如何给对象的属性赋值。
如果对象由我们自己创建,这一切都变得很简单,例如:

User user = new User();
user.setName("小智"); //通过setName方法为name属性赋值
user.setAge(24); //通过setAge方法为age属性赋值

或者:

User user = new User("小智", 24); //在创建对象的同时,通过有参构造函数为对象的属性赋值

若是对象由Spring IoC容器创建,Spring提供两种方式为属性赋值:

1)set方法注入
2)构造方法注入
set方法注入
顾名思义,就是在类中提供需要注入成员的 set 方法。spring框架底层会调用set方法为成员变量赋值。
例如:Spring框架负责创建User的Bean对象之后,会通过调用User对象的setName方法为name属性赋值。
普通属性注入
需求:通过Spring IoC容器获取User实例,并为User对象的name和age属性(普通属性)赋值
1、在User类中声明name和age属性,并添加对应的setter和getter方法,以及重写toString方法

public class User {
//提供私有成员变量
private String name;
private Integer age;
private UserInfo info;
//提供getter和setter方法
...
//重写toString方法
...
}

2、在beans.xml中声明User类的bean实例

<!-- 将User类作为bean装配到Spring IoC容器中(即User类的实例由Spring创建) -->
<bean id="user" class="com.tedu.pojo.User"></bean>

3、创建测试类—DITest

package com.tedu;
import org.Springframework.context.support.ClassPathXmlApplicationContext;
public class DITest {
@Test
public void testDI() {
// 获取Spring的IoC容器
ApplicationContext ctx = new
ClassPathXmlApplicationContext("beans.xml");
// 使用getBean方法获取对应的POJO并输出
User user = (User)ctx.getBean( "user" );
System.out.println( user );
}
}

由于这里没有为User对象的属性赋值,所以此时运行测试,结果为:

User[name=null,age=null,info=null]

4、修改beans.xml中User Bean标签,为User Bean的name和age属性注入属性值

<!-- 将User类作为bean装配到Spring IoC容器中(即User类的实例由Spring创建) -->
<bean id="user" class="com.tedu.pojo.User">
<!-- 通过set方法为User Bean的name、age属性赋值 -->
<property name="name" value="小智"/>
<property name="age" value="24"/>
</bean>

上面的bean定义表明,User bean通过 <property> 标签为User对象的 name 和 age 属性赋值。
之所以称之为是set方法注入,是因为在框架底层会调用User对象的setter方法为属性赋值。
例如:下面User bean标签中的 <property> 标签是为User对象的属性赋值。

<property name="name" value="小智"></property>

因为 name=" name ",因此需要User对象中有setName方法才可以完成注入,否则将会注入失败。
value=" 小智 ",表示为(User对象的) setName 方法对应的属性赋值为" 小智"。

普通属性(基本数据类型和String类型)直接通过value注入即可。

5、运行测试类DITest,结果为:

User[name="小智",age=24,info=null]

对象属性注入
需求:通过Spring IoC容器获取User实例,并为User对象的userInfo属性(对象属性)赋值

1、在beans.xml中,将UserInfo类作为bean装配到Spring IoC容器中(如果已有可以忽略)

<!-- 将UserInfo类作为bean装配到Spring IoC容器中(即UserInfo类的实例由Spring创建) -->
<bean id="userInfo" class="com.tedu.pojo.UserInfo"></bean>

2、在beans.xml中,将通过 Spring 容器获取的UserInfo对象作为值,注入到User对象的userInfo属性

<!-- 将User类作为bean装配到Spring IoC容器中(即User类的实例由Spring创建) -->
<bean id="user" class="com.tedu.pojo.User">
<!-- 通过set方法为User Bean的name、age属性赋值 -->
<property name="name" value="小智"/>
<property name="age" value="24"/>
<!-- 通过set方法为User Bean的info(对象)属性赋值 -->
<property name="info" ref="userInfo"/>
</bean>
<!-- 将UserInfo类作为bean装配到Spring IoC容器中(即UserInfo类的实例由Spring创建) -->
<bean id="userInfo" class="com.tedu.pojo.UserInfo"></bean>

由于此处是将UserInfo对象的引用作为值设置给info属性,因此 ref 属性指定为UserInfo对象bean标签的id值。将通过 Spring 容器获取的UserInfo对象传递给setUserInfo方法,从而对User对象的属性赋值。

对象属性通过ref属性注入。

3、运行测试类DITest,结果为:

User[name="小智",age=24,info=com.tedu.pojo.Userinfo@65e2dbf2]

构造方法注入
顾名思义,就是使用类中的构造函数,为成员变量赋值——即构造方法注入。
需要注意的是:为成员变量赋值是通过配置的方式,让spring框架在创建bean对象的同时,为成员变量赋值。而不是我们自己去实现。
需求:通过Spring IoC容器获取User实例,并为User对象的name、age、info属性赋值

1、为User类添加无参构造和有参构造函数

//提供无参构造
public User() { }
//提供有参构造
public User(String name, Integer age, UserInfo info) {
this.name = name;
this.age = age;
this.info = info;
}

注意:如果不添加有参构造函数,可以无参、有参构造函数都不添加;

如果要添加有参构造函数,强烈建议同时添加无参构造函数,否则在很多地方使用时都可能会抛出异常!

2、修改beans.xml文件,将set方法修改为构造方法注入。

<!-- 将User类作为bean装配到Spring IoC容器中(即User类的实例由Spring创建) -->
<bean id="user" class="com.tedu.pojo.User">
<!-- 通过set方法为User Bean的name、age属性赋值
<property name="name" value="小智"/>
<property name="age" value="24"/> -->
<!-- 通过set方法为User Bean的info(对象)属性赋值
<property name="info" ref="userInfo"/> -->
<!-- 通过构造方法为User Bean的name、age、info属性赋值 -->
<constructor-arg name="name" value="马云"/>
<constructor-arg name="age" value="30"/>
<constructor-arg name="info" ref="userInfo"/>
</bean>
<!-- 将UserInfo类作为bean装配到Spring IoC容器中(即UserInfo类的实例由Spring创建) -->
<bean id="userInfo" class="com.tedu.pojo.UserInfo"></bean>

其中,constructor-arg标签name属性的值必须和构造函数中参数的名字相同!

同样的,普通属性直接通过value注入即可;对象属性通过ref属性注入。

3、运行测试类DITest,结果为:
User[name=马云,age=30,info=com.tedu.pojo.UserInfo@7e3f631b]

以上是关于SpringDI依赖注入的主要内容,如果未能解决你的问题,请参考以下文章

SpringDI 依赖注入传递参数的方式

SpringDI--依赖注入(注解方式)

注意细节,阿里架构师一文详解SpringDI的四种依赖注入方式

SpringIoC与SpringDI

Play 框架依赖注入

Spring IoC 依赖注入的方法大全