依赖项注入(DI)是一个过程,在这个过程中,对象仅通过构造函数参数、工厂方法的参数或从工厂方法构造或返回后在对象实例上设置的属性来定义它们的依赖项(即它们与之一起工作的其他对象)。然后容器在创建bean时注入这些依赖项。这个过程基本上是bean本身的逆过程(因此称为控制反转过程),由对象自己控制实例化或者定位他的依赖,改变为通过直接使用类的构造方法或者使用服务定位模式。
依赖:bean对象的创建依赖于容器
注入:bean对象中的所有属性,由容器来注入
一、构造器注入
基于构造函数的DI是通过容器调用带有许多参数的构造函数来完成的,每个参数代表一个依赖项。调用带有特定参数的静态工厂方法来构造bean几乎是等价的,本讨论将参数分别用于构造函数和静态工厂方法。下面的例子展示了一个只能依赖注入构造函数注入的类:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String name;
private int age;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Score {
private int English;
private int Math;
}
(1)构造参数名注入
<bean id="user" class="com.leishida.spring.User">
<constructor-arg name="name" value="构造器注入"/>
<constructor-arg name="age" value="18"/>
<!-- 当对象内部的属性是引用类型时,通过ref引用上面注册的score Bean -->
<constructor-arg name="score" ref="score"/>
</bean>
(2)索引注入
<bean id="user1" class="com.leishida.spring.User">
<constructor-arg index="0" value="索引"/>
<constructor-arg index="1" value="18"/>
<constructor-arg index="2" ref="score"/>
</bean>
(3)构造参数类型注入
<bean id="user2" class="com.leishida.spring.User">
<constructor-arg type="java.lang.String" value="类型"/>
<constructor-arg type="int" value="18"/>
<constructor-arg type="com.leishida.spring.Score" ref="score"/>
</bean>
二、Set方式注入(重点)
基于setter的DI是在调用无参数构造函数或无参数静态工厂方法来实例化bean之后,通过容器调用bean上的setter方法来完成的。
这种注入方式要求一定得有Set方法!
1.Student 实体类
@Data
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
public void setName(String name) {
this.name = name;
}
public void setAddress(Address address) {
this.address = address;
}
public void setBooks(String[] books) {
this.books = books;
}
public void setHobbys(List<String> hobbys) {
this.hobbys = hobbys;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public void setGames(Set<String> games) {
this.games = games;
}
public void setWife(String wife) {
this.wife = wife;
}
public void setInfo(Properties info) {
this.info = info;
}
public void show(){
System.out.println("name="+ name
+ ",address="+ address.getAddress()
+ ",books="
);
for (String book:books){
System.out.print("<<"+book+">>\t");
}
System.out.println("\n爱好:"+hobbys);
System.out.println("card:"+card);
System.out.println("games:"+games);
System.out.println("wife:"+wife);
System.out.println("info:"+info);
}
}
}
2. Address 实体类
@Data
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
3. 注入
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.kuang.pojo.Address">
<property name="address" value="NJUPT9"/>
</bean>
<bean id="student" class="com.kuang.pojo.Student">
<!--第一种,普通值注入,value-->
<property name="name" value="狂神"/>
<!--第二种,Bean注入-->
<property name="address" ref="address"/>
<!--数组-->
<property name="books">
<array>
<value>红楼</value>
<value>三国</value>
</array>
</property>
<!--List-->
<property name="hobbys">
<list>
<value>music</value>
<value>swimming</value>
<value>coding</value>
</list>
</property>
<!--Map-->
<property name="card">
<map>
<entry key="身份证" value="12312121212"/>
<entry key="银行卡" value="678112121111000"/>
</map>
</property>
<!--Set-->
<property name="games">
<set>
<value>CF</value>
<value>LOL</value>
<value>GTA</value>
</set>
</property>
<!--null-->
<property name="wife">
<null/>
</property>
<!--Properties-->
<property name="info">
<props>
<prop key="学号">20190526</prop>
<prop key="username">root</prop>
<prop key="password">root</prop>
</props>
</property>
</bean>
</beans>
三、拓展方式注入
C命名空间注入:实际上就是有参构造注入
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="john-classic" class="com.example.Person">
<property name="name" value="John Doe"/>
<property name="spouse" ref="jane"/>
</bean>
<bean name="john-modern"
class="com.example.Person"
p:name="John Doe"
p:spouse-ref="jane"/>
<bean name="jane" class="com.example.Person">
<property name="name" value="Jane Doe"/>
</bean>
</beans>
P命名空间注入:
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="classic" class="com.example.ExampleBean">
<property name="email" value="someone@somewhere.com"/>
</bean>
<bean name="p-namespace" class="com.example.ExampleBean"
p:email="someone@somewhere.com"/>
</beans>