Spring 之IOC
一.IoC 简介
IOC 反转控制, 原来的程序需要自己创建实现类的对象!现在实现类对象创建权,交由Spring 框架管理,程序需要只需从IOC 容器中获取对象即可!
IOC 的作用: 解除了软件中对象之前的耦合
DI (Dependencies Injection) 依赖注入
依赖注入就是在IOC 容器运行期间,动态的将某种依赖关系注入到对象之中!
IOC 和DI 区别:
- IOC 和DI 其实是同一事件!
- IOC 强调 将对象的创建权限,交给Spring 容器!
- DI 强调IOC 容器中对象的依赖关系,被动态的注入到对象中!
二.IoC 容器装配 Bean (XML)
2.1. Bean 实例化
第一种: 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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- id 属性也可以写成name --> <bean id="bookDao" class="com.zhgboy.mysprng.dao.BookDAOIpml"></bean> </beans>
注意:如果该类没有无参的构造器时,会出现报错
2.2 Bean 作用域
<Bean> 元素内,提供scope 属性,用于 指定Bean 的作用域
Prototype Bean 在ApplicationContext 初始化时,不会被创建.而是在getBean 时,才会构造一个新的对象!
2.3 Bean 的生命周期
<bean> 元素 提供 init-method 和destory-method 用于指定Bean 的初始化和销毁的方
public class LifeCycleBean { public LifeCycleBean(){ System.out.println("LifeCycleBean 开始创建对象了 ...."); } // 初始化 方法 必须是非静态,共有的,无法返回值,无参数的方法 public void setup(){ System.out.println(" LifeCycleBean 被IOC 容器初始化了 .... "); } // 销毁方法 必须是非静态,共有的,无法返回值,无参数的方法 public void tearDown(){ System.out.println("LifeCycleBean 被IOC 销毁了 .... "); } }
<!-- Bean 的生命周期 --> <bean name="" class="com.zhgboy.mysprng.business.LifeCycleBean" init-method="setup" destroy-method="tearDown" />运行后结果:
tearDown 销毁的方法没有执行!
1. 只有singleton 作用域才能执行销毁,prototype作用域一定不会执行销毁
2. 必须 sping 的容器 调用 close 方法时.才会执行单例对象的销毁
2.4 Bean 的属性依赖注入
2.4.1 依赖注入方法
大致有三中,分别是 构造参数注入; 属性 setter 方法注入 ; 接口注入
注意: Spring 框架 通过 配置,完成 构造器注入和setter
方法注入,不支持接口注入!
2.4.2 构造器注入
通过类的构造函数,向成员变量 进行赋值! 通过 <Bean > 元素中的 <constructor-arg > 配置构造方法!
<bean name="cunfu" class="com.zhgboy.mysprng.pojo.Student"> <!-- 构造器参数 --> <!-- name 表示 参数的名称 index 表示 第几个参数 type 表示参数的类型 value 参数的值,仅仅注入简单类型值 ref 注入复杂Bean 对象的引用,(引用另一个bean 的name或id) --> <constructor-arg index="0" type="java.lang.String" value="邱淑贞"/> <constructor-arg index="1" type="int" value="165"/> </bean>2.4.3 属性setter 方法注入
针对属性 setter 方法,Spring 框架根据setter 方法属性规则进行注入! 通过<Bean > 元素中 的<property> 进行注入数据
属性注入图解:
2.4.4 集合类型属性注入
Spring 支持 java.utils 包集合类型
三.IoC 容器装配 Bean (注解)
3.1 Bean 扫描配置的注解
注解Component,在类的开头使用了@Componet 注解,可以被Spring 容器识别, 启动Spring 后,会自动把它转成容器管理的Bean!
除了 @Component 外,Spring 另外提供了3个基本和@Componet等效的注解!分别 对应于DAO,Service 和Controller 进行注解!
@Respository 用于对DAO 实现类进行注解,
@Service 用于对业务层进行注解, 通常用于Service 业务层!
@Controller 用于对控制层注解,通常用于 Controller 控制层!
@Componet 泛指组件,当组件不好归类的时候,可以使用该注解进行注解!
注解对应xml 配置文件支持:使用context 名称空间!下划线加粗的schma!
<?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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <context:component-scan base-package="com.zhgboy.mySpring.ioc"></context:component-scan> </beans>
<!-- 自动扫描com.zhgboy.anno.bo中的类进行扫描 -->
<context:component-scan base-package="com.zhgboy.anno.bo" resource-pattern="bo/*.class" />
<context:component-scan base-package="com.zhgboy.anno" >
<context:include-filter type="aspectj“ expression="com.zhgboy.anno.dao.*.*"/>
<context:exclude-filter type=“aspectj” expression=“com.zhgboy.anno.entity.*.*”/>
</context:component-scan>
include-filter表示需要包含的目标类型,exclude-filter表示需要排除的目标类型,type表示采的过滤类型,共有如下5种类型:
Filter Type | Examples Expression | Description |
annotation | org.example.SomeAnnotation | 注解了SomeAnnotation的类 |
assignable | org.example.SomeClass | 所有扩展或者实现SomeClass的类 |
aspectj | org.example..*Service+ | AspectJ语法表示org.example包下所有包含Service的类及其子类 |
regex | org\.example\.Default.* | Regelar Expression,正则表达式 |
custom | org.example.MyTypeFilter | 通过代码过滤,实现org.springframework.core.type.TypeFilter接口 |
expression表示过滤的表达式。
①如果仅希望扫描特定的类而非基包下所有的类, 可以使用resource-pattern 属性过滤特定的类
<context:component-scan base-package="com.zhgboy.mySpring" resource-pattern="ioc/A*.class"> </context:component-scan>
②只扫描com.zhgboy.mySpring.ioc下所有名称以A开始的类。
<context:component-scan base-package="com.zhgboy.mySpring.ioc.anno" > <context:include-filter type="aspectj" expression="com.zhangguo.anno.dao.*.*"/> <context:exclude-filter type="aspectj" expression="com.zhangguo.anno.entity.*.*"/> </context:component-scan>
④ 排除以B 开头的类
<!--指定要扫描的包,如果有多个可以用逗号隔开-->
<context:component-scan
base-package="com.zhgboy.mySpring.ioc.anno.service,com.zhgboy.mySpring.ioc.anno.dao">
<context:exclude-filter type="regex" expression="com.zhgboy.mySpring.ioc.anno\.B.*"></context:exclude-filter> </context:component-scan>3.2 Bean 作用域 @scope
@Component @Scope("prototype") //也可以设置request,session public class BookService {@Scope 来指定Bean 的作用域!
3.3 注解指定名称
如果使用Compont 注解是,不指定名称,基于@Componet 及其扩展(@Service,@Controller,@Respository 等,)标准和classpath-scan 定义的Bean, 注解有一个value 属性,用来指定Bean 的名字,如果不提供,就会使用Spring 默认的命名机制,即类名第一个字母小写!
3.4 注解配置Bean 的初始化和销毁方法
@PostContruct 相当于 init-method 指定初始化方法
@PreDestory 相当于 destory-method 指定对象销毁方法
3.5 Bean 属性注入的相关注解
属性注入的相关注解有: @Autowired ,@Resource ,@Qualifier
@Autowired 默认是按照类型装配注入的,如果需要按照名称来装配注入,则需要结合@Qaulifier 一起使用!
@Resource 默认是按照名称来装配注入的,只有找不到与名称匹配的Bean 才会按照类型进行装配注入!
@Qualifier 需要指定Bean 名称进行装配注入!
@Autowired 是由Spring 框架提供的,而@Resource 是J2EE 提供的!
@Autowired 可以对成员变量,方法,构造参数 进行注解,而@Qualifier 的注解对象是成员变量,方法入参构造函数入参!
@Autowird 注解进行自动注入时,Spring 容器中匹配的时候,Bean 的数目必须有且仅有一个,可以通过属性required 可以设置非必要
@Resource 装配顺序
- 如果同时指定了 name和type ,则从Spring 的Context 中得到唯一的Bean 进行装配,找不到则抛异常!
- 如果 指定了name , 则从Spring 的Context 中查找名称(或id) 匹配的Bean 进行装配,找不到则抛异常!
- 如果指定了 type ,则从Spring 的Context 中查找类型匹配唯一的Bean 进行装配,找不到则抛异常!
- 如果都没有指定,则自动安装byName 方式进行装配,如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配
3.6 替代 xml 配置文件中<context> 元素 相关的注解
@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器.