文章目录
依赖注入概念
依赖注入 (DI) 是一个过程,其中对象仅通过构造函数参数、工厂方法的参数或在对象实例被构造或从工厂方法返回。然后容器在创建 bean 时注入这些依赖项。
这个过程基本上是 bean 本身的逆过程(因此得名,控制反转),通过使用类的直接构造或服务定位器模式自行控制其依赖项的实例化或位置。
DI 原则使代码更清晰,当对象提供依赖关系时,解耦更有效。
该对象不查找其依赖项,也不知道依赖项的位置或类。
因此,您的类变得更容易测试,特别是当依赖项位于接口或抽象基类上时,这允许在单元测试中使用存根或模拟实现。
DI 存在两种主要变体:基于构造函数的依赖注入和基于 Setter 的依赖注入。
-
依赖注入(Dependency Injection,DI)。
-
依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 .
-
注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配 .
基于构造函数的依赖注入
在学习记录02中已经写过了
基于 Setter 的依赖注入
基于 Setter 的依赖注入要求被注入的属性必须有set方法 ,set方法的方法名由set + 属性首字母大写
Student.java
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbies;
private Map<String,Object> card;
private Set<String> games;
private String wife;
private Properties info;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
public Map<String, Object> getCard() {
return card;
}
public void setCard(Map<String, Object> card) {
this.card = card;
}
public Set<String> getGames() {
return games;
}
public void setGames(Set<String> games) {
this.games = games;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
}
Address.java
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
通过各种类型的注入方式来注入
常量注入
通过name-value来实现注入
<bean id="address" class="com.wcy.pojo.Address">
<property name="address" value="北京"/>
</bean>
引用注入
值为已经注册好的实体类
<property name="address" ref="address"/>
数组注入
<property name="books">
<array>
<value>西游记</value>
<value>水浒传</value>
</array>
</property>
map注入
<property name="card">
<map>
<entry key="name" value="wcy"/>
<entry key="age" value="18"/>
<entry key="address" value-ref="address"/>
</map>
</property>
list注入
<property name="hobbies">
<list>
<value>打球</value>
<value>聊天</value>
</list>
</property>
set注入
<property name="games">
<set>
<value>cf</value>
<value>lol</value>
</set>
</property>
properties注入
和map的区别是,map将值写在value属性中,二prop将值写在中间
<property name="info">
<props>
<prop key="qq">123456</prop>
<prop key="email">123456@163.com</prop>
</props>
</property>
null和空字符串注入
<property name="wife">
<null/>
</property>
<property name="name" value=""/>
结果
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student);
}
Student{
name='',
address=com.wcy.pojo.Address@768b970c,
books=[西游记, 水浒传],
hobbies=[打球, 聊天],
card={name=wcy, age=18, address=com.wcy.pojo.Address@768b970c},
games=[cf, lol], wife='null',
info={qq=123456, email=123456@163.com}
}
p命名空间和c命名空间注入
p命名空间和从命名空间分别代表property和construction注入的另一种方式,比较简洁
p命名空间注入
需要先导入约束
xmlns:p="http://www.springframework.org/schema/p"
通过p:xxx="xx"的方式注入
<bean id="student" class="com.wcy.pojo.Student" p:name="wcy"/>
c命名空间注入
xmlns:c="http://www.springframework.org/schema/c"
通过c:xxx="xx"的方式注入
使用c命名空间注入的方式,一定要有有参构造!
<bean id="student" class="com.wcy.pojo.Student" c:name="wcy"/>
Bean的作用域
在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean。简单地讲,bean就是由IoC容器初始化、装配及管理的对象 .
作用域 | 描述 |
---|---|
singleton | 使用该属性定义Bean时,IOC容器仅创建一个Bean实例,IOC容器每次返回的是同一个Bean实例。 |
prototype | 使用该属性定义Bean时,IOC容器可以创建多个Bean实例,每次返回的都是一个新的实例。 |
request | 该属性仅对HTTP请求产生作用,使用该属性定义Bean时,每次HTTP请求都会创建一个新的Bean,适用于WebApplicationContext环境。 |
session | 该属性仅用于HTTP Session,同一个Session共享一个Bean实例。不同Session使用不同的实例。 |
application | 该属性仅用于HTTP Session,同session作用域不同的是,所有的Session共享一个Bean实例。 |
request、session作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于web的Spring ApplicationContext环境
Singleton
当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。
Spring中Bean默认的作用域就是singleton,当然也可以手动配置
<bean id="student" class="com.wcy.pojo.Student" p:name="wcy" scope="singleton"/>
测试:
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
Student student1 = (Student) context.getBean("student");
System.out.println(student==student1); //true
}
prototype
Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。
Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。
<bean id="student" class="com.wcy.pojo.Student" p:name="wcy" scope="prototype"/>
测试:
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
Student student1 = (Student) context.getBean("student");
System.out.println(student==student1); //false
}