Spring 之IOC

一.IoC 简介

 IOC 反转控制, 原来的程序需要自己创建实现类的对象!现在实现类对象创建权,交由Spring 框架管理,程序需要只需从IOC 容器中获取对象即可!

IOC 的作用: 解除了软件中对象之前的耦合

Spring 之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>

 注意:如果该类没有无参的构造器时,会出现报错

Spring 之IOC

2.2 Bean 作用域

         <Bean> 元素内,提供scope 属性,用于 指定Bean 的作用域

Spring 之IOC

      singleton Bean 在ApplicationContext 容器对象初始化时,就会被创建。

      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 之IOC注意: 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> 进行注入数据  

 属性注入图解:   

Spring 之IOC  2.4.4 集合类型属性注入

Spring 支持 java.utils 包集合类型


Spring 之IOC
Spring 之IOC
Spring 之IOC
Spring 之IOC

三.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>
增加了注解扫描的范围,可以指定一个包,通过属性设置更加精确的范围:
<context> 标记常用属性配置:
     componet-scan base-package 指定支持此注解的包的范围路径!
     resource-pattern : 对指定的基包 下面的子包进行选取!
<Context> 子标记 :
   include - filter : 指定需要包含的包
   exclude-filter : 指定需要排除的包
  

<!-- 自动扫描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开始的类。

    扫描注解了org.springframework.stereotype.Repository的类  exclude-filter表示排除,include-filter表示包含,可以有多个
<context:component-scanbase-package="com.zhgboy.mySpring.ioc"> 
<context:exclude-filtertype="annotation" expression="org.springframework.stereotype.Repository"/> <context:include-filtertype="annotation" expression="org.springframework.stereotype.Service"/> </context:component-scan>

   ③ 只扫描 aspectj 类型,到下所有的类,排除entity 下所有的类
  <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">

<!--使用正则排除以B开头的类-->
   <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 指定对象销毁方法

  Spring 之IOC

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容器.