2 控制反转
2.1 IoC概念
控制反转(Inversion of Control,IoC)把对象创建的权利交给框架来处理,包括依赖注入与依赖查找,目的是削减程序耦合。
2.2 使用Spring IoC
step1:在resources目录下创建bean.xml文件
step2:配置bean.xml
- 添加文档约束,访问Spring网站 ,找到【1.2.1. Configuration Metadata】,将里面的xml拷贝到bean.xml中
- 配置bean
<?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">
<!-- 把对象的创建交给spring处理
id:获取bean时指定的名字
class:bean的全限定类名
-->
<bean id = 'accountService' class="com.dnm.ioc.service.impl.AccountServiceImpl"></bean>
</beans>
step3:获取bean
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IAccountService as = (IAccountService) ac.getBean("accountService");
as.saveAccount();
}
ApplicationContext的三个实现类
ClassPathXmlApplicationContext(String beanPath)
:获取类路径下的配置文件以创建容器(较常用)FileSystemXmlApplicationContext(String beanPath)
:获取绝对路径下的配置文件以创建容器AnnotationConfigApplicationContext()
:获取注解配置以创建容器
2.3 核心容器的两个接口
ApplicationContext
:饿汉式bean初始化,读取完配置后便进行初始化BeanFactory
:懒汉式bean初始化,在使用的时候才进行初始化
2.4 Bean的作用范围
Spring默认采用单例模式,可以使用scope属性更改作用范围,主要由以下几种:
- singleton:单例(默认值)
- prototype:多例的
- request:作用域web应用的请求范围
- session:作用于web的会话范围
- global-session:作用于集群环境的会话范围
2.5 Spring的依赖注入
能够注入的类型
- 基本类型与String
- 其他bean
- 复杂类型/集合类型
能够注入的方式
- 使用构造函数
- 使用set方法
- 使用注解
建议的注入数据:
- 不频繁改变的数据
2.5.1 构造器注入
示例
bean.xml配置文件
<!-- 构造函数注入:
使用标签: constructor-arg(Bean标签的内部)
标签属性:
type:注入的数据类型
index:注入参数索引位置(从0开始)
name:用于指定给构造函数中参数名称赋值(常用)
==================以上用于找到指定参数======================
value:用于给基本类型或String赋初值
ref:用于指定其他的bean类型数据
-->
<bean id = 'accountService' class="com.dnm.ioc.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<bean id="now" class="java.util.Date"></bean>
AccountServiceImpl.java
public class AccountServiceImpl{
// 经常变化的数据,并不适用于注入
private String name;
private Integer age;
private Date birthday;
public AccountServiceImpl(String name, Integer age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
@Override
public String toString() {
return "AccountServiceImpl{" +
"name='" + name + '\'' +
", age=" + age +
", birthday=" + birthday +
'}';
}
}
特点:
- 在获取bean对象时,注入是必须的操作,否则对象无法创建成功。
- 改变了bean的实例化方式,即使不使用部分数据也必须初始化,否则需要定义多个构造函数
2.5.2 set方法注入
<!-- 构造函数注入:
使用标签: property(Bean标签的内部)
标签属性:
name:用于指定给构造函数中参数名称赋值
value:用于给基本类型或String赋初值
ref:用于指定其他的bean类型数据
要求:对应类实现setter方法
-->
<bean id = 'accountService2' class="com.dnm.ioc.service.impl.AccountServiceImpl2">
<property name="name" value="泰斯特"></property>
<property name="age" value="18"></property>
<property name="birthday" ref="now"></property>
</bean>
特点:
- 在获取bean对象时,依赖注入更加灵活
- 无法保证某个成员必须有值
2.5.3 复杂类型注入
<!-- 复杂类型的注入
list结构使用标签:list、array、set
map结构使用标签:map、props标签
-->
<bean id = 'accountService3' class="com.dnm.ioc.service.impl.AccountServiceImpl3">
<property name="myStrs">
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</list>
</property>
<property name="myList">
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>
<property name="mySet">
<array>
<value>AAA</value>
<value>BBB</value>
<value>BBB</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>
<property name="myMap">
<map>
<entry key="testA" value="AAA"></entry>
<entry key="testB" value="BBB"></entry>
</map>
</property>
<property name="myProps">
<props>
<prop key="testC">CCC</prop>
<prop key="testD">DDD</prop>
</props>
</property>
</bean>