spring-ioc容器

IOC(inverse of control,控制-反转)

一、ioc概述

1.ioc的类型

        ioc主要可以划分成三种类型:构造函数注入属性注入接口注入


 
2.通过容器完成依赖关系注入:

        通过xml的方式配置Bean,在容器启动时,spring根据xml配置文件的
        描述信息自动实例化Bean并完成依赖关系的装配,
        这种实例化并注入依赖的能力是通过java的反射来实现的


        
二、相关java基础知识

    java语言允许通过程序化的方式间接对Class进行操作。
    Class文件有类装载器装载后, 在JVM中将形成一份描述Class结构的元信息对象,
    通过该元信息对象可以获知Class的结构信息,如构造函数、属性和方法等。
    Java允许用户借由这个与Class相关的元信息对象间接调用Class对象的功能,
    这就为使用程序化方式操作Class对象开辟了途径


    
 1、类装载器就ClassLoader


 
    类装载器就是寻找类的字节码文件并构造出类在JVM内部表示对象的组件
    类装载器把一个类装入JVM中,需要经过一下步骤:
    (1)装载:查找和导入Class文件
    (2)链接:执行校验、准备和解析步骤,其中解析步骤是可以选择的。
        ①校验:检查载入Class文件数据的正确性
        ②准备:给类的静态变量分配存储空间
        ③解析:将符号引用转换为直接引用
    (3)初始化:对类的静态变量、静态代码块执行初始化工作
    


JVM装载类的时使用“全盘负责委托机制”

    “全盘负责”:是指当一个ClassLoader装载一个类时,除非显式地使用另一个“ClassLoader”,
    该类所依赖及引用的类也有这个ClassLoader载入;
    
    “委托机制”:是指先委托父装载器寻找目标类,只有在找不到的情况下才从自己的类路径中查找
    并装载目标类;
    
    正因为有了“全盘负责委托机制”,java.lang.String 永远是由根装载器来装载的,
    避免有人编写一个恶意的基础类(例如String)装载到JVM中


    
 2.java反射机制
 


    Class反射对象描述类的语义结构,
    从Class对象可以获取构造函数、成员变量、方法类等类元素的反射对象
    主要的反射类有三个:Controller、Method、Field  其他还有package、AnnotatedElement反射类
    在访问private或protected成员变量或方法时,必须通过setAccessible(boolean access)方法取消
    java语言检查,否则将抛出IllegalAccessException


三、资源访问利器 Resource

 

1、资源抽象接口

 

    spring Resource接口为应用提供了更强的底层资源访问能力。该接口拥有对应不同资源类型的实现类
    主要方法:
        > boolean exists(): 资源是否存在
        > boolean isOpen(): 资源是否打开
        > URL getUTL() throws IOException: 如果底层资源可以表示成URL,则该方法返回对应不同类型的实现类
        > File getFile() throws IOException: 如果底层资源对应一个文件,则该方法返回对应的File对象
        > InputStream getInputStream() throws IOException: 返回资源对应的输入流
    > WritableResource: 可写资源接口 实现类有FileSystemResource和PathResource
    > ByteArrayResource: 二进制数组表示的资源
    > ClassPathResource: 类路径下的资源
    > FileSystemResource: 文件系统资源
    > InputStreamResource: 以输入流返回表示的资源
    > ServletContextResource: 为访问Web容器上下文中的资源而设计的类
    > UrlResource: 使用户能够访问任何可以通过URL表示的资源
    > PathResource: spring4.0提供读取资源文件的一个通用类
    


2、资源加载


    spring能通过不同的资源地址前缀识别不同的资源类型。支持Ant风格通配符资源地址:? * **
    资源地址前缀有:classpath:、file:、http://、ftp://等。
    或者是没有前缀,根据ApplicationContext的具体实现类采用对应类型的Resource
    
    在发布时如果资源配置文件被打包到jar包中。recource.getFile就无法读取了,
    从而造成部署实施时出现意想不到的问题。因此我们建议尽量以流的方式读取
    避免环境不同造成问题


    
四、BeanFactory和ApplicationContext


    spirng通过配置文件描述Bean与Bean之间的依赖关系,利用Java语言的反射功能实例化Bean并建立Bean之间的依赖关系。
    springIOC的容器在完成这些底层工作的基础上还提供了Bean实例缓存、生命周期管理、Bean实例代理、事件发布、资源装载等高级服务。
    BeanFactory是spring框架最核心的接口,它提供了高级IOC的配置机制
    BeanFactory是IOC容器,ApplicationContext为应用上下文,也称为Spring容器
    BeanFactort是Spring框架的基础设施面向Spring本身;ApplicationContext面向使用Spring框架的开发者


    1.BeanFactory在初始化容器时没有实例化Bean,直到第一次访问某个Bean时才实例化目标Bean
      而ApplicationContext则在初始化应用上下文时就实例化所有单实例的Bean。
        因此ApplicationContext的初始化时间会比BeanFactory稍长一些,不过稍后的调用则没有“第一次惩罚”的问题
    
    2.通过HierarchicalBeanFactory接口,spring的IOC容器可以建立父子层级关联的容器体系
        子容器可以访问父容器中的Bean,但父容器不能访问子容器中的Bean。
        在容器内,Bean的Id必须是唯一的,但子容器可以拥有一个和父容器id相同的Bean。

五、Bean的生命周期


    Bean生命周期多个特定的生命阶段组成,每个生命阶段都开出了一扇门,允许外界借由此门对Bean施加控制
    spring中可以从两层面定义Bean的生命周期: 
        第一个层面是Bean的作用范围
        第二个层面是实例化Bean时所经历的一系列阶段       


1.BeanFactory中Bean的生命周期


    1.当调用者通过getBean(beanName)向容器请求某一个Bean时,如果容器注册了
        org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口
      ,实例化Bean之前,将调用接口的postProcessBeforeInstantiation方法。
    2.根据配置情况调用Bean构造函数或工厂方法实例化Bean
    3.如果容器注册了InstantiationAwarePostProcessor接口,那么在实例化Bean之后,
      用该接口的postProcessAfterInstantiation()方法,可在这里对已经实例化的对象进行梳理打扮
    4.如果Bean配置了属性信息,那么容器在这一步着手将配置值设置到Bean对应的属性中,不过在设置每个属性之前
      将先调用InstantiationAwareBeanPostProcessor接口的postProcessValues()方法。
    5.调用Bean的属性设置方法设置属性值
    6.如果Bean实现了 org.springframework.beans.factory.BeanNameAWare 接口,则将调用setBeanName()接口方法,
      将配置文件中该Bean对应的名称设置到Bean中
    7.如果Bean实现了org.springframework.beans.factory.BeanFactoryAware接口,则将调用setBeanFactory()接口方法,
      将BeanFactory容器实例设置到Bean中。
    8.如果BeanFactory装配了org.springframework.beans.factory.config.BeanPostProcessor后处理器,
      则将嗲用BeanPostProcessor的Object postProcessBeforeInitialzation(Object bean,String beanName)接口方法
      对Bean进行加工操作。
        其中入参bean是当前正在处理的Bean,而beanName是当前Bean的配置名,返回的对象为加工处理后的Bean
        用户可以使用该方法对某些Bean进行特殊处理,甚至改变Bean的行为。
        BeanPostProcessor在Spring框架中占有重要的地位,为容器提供对Bean后续加工处理的切入点
        Spring提供的AOP、动态dialing等功能都通过BeanPostProcessor实施
    9.如果Bean实现了InitialzaingBean接口,则将调用接口的afterPropertiseSet()方法
    10.如果<bean>中通过init-method属性定义了初始化方法,则将执行这个方法。
    11.BeanPostProcessor后处理器定义了两个方法:
        其一是postProcessBeforeInitialization(),在第8步调用;
        其二是Object postProcessAfterInitialization(Object bean,String beanName),这个方法在此时调用,
              容器再次获得对Bean进行加工处理的机会
    12.如果在<bean>中指定Bean的作用范围为scope = "prototype",则将Bean返回给调用者,调用者负责Bean后续的生命管理,
       spring不再管理这个Bean的生命周期。如果将作用范围设置为scope="singleton",则将Bean放入SpringIoc容器的缓存池中,
       并将Bean引用返回给调用者,Spring继续对这些Bean进行后续的生命管理。
    13.对于scope="singleton"的Bean(默认情况),当容器关闭时,将触发Spring对Bean后续生命周期的管理工作。
       如果Bean实现了DisposableBean接口,将调用接口destroy方法,可以在此编写释放资源,记录日志等操作。
    14.对于scope="singleton"的Bean,如果通过<bean>的destroy-method属性指定了Bean的销毁方法,那么Spring将执行Bean等的这个方法,
      完成Bean资源的释放等操作。


BeanFactory生命周期总结


    Bean完整的生命周期中方法大致可以分为四类:
        1.Bean自身的方法:
            如调用Bean构造函数实例化Bean、调用Setter设置Bean的属性值及通过<bean>的init-method和destroy-method所指定的方法
        2.Bean级生命周期接口方法:
            如BeanNameAware、BeanFactoryAware、InitializatingBean和DisposableBean,这些接口方法有Bean类直接实现
        3.容器级生命周期接口方法:
            由InstantiationAwareBeanPostProcessor和BeanPostProcessor这两个接口实现的,一般称他们的实现类为“后处理器”。
            后处理器接口一般不由Bean本身实现,他们独立于Bean,实现类以容器附加装置的形式注册到Spring容器中,并通过接口
            反射为Spring容器扫描识别。当Spring容器创建任何Bean的时候,这些后处理器都会发生作用,所以这些处理器的影响是全局性的。
            当然,用户可以通过合理地编写后处理器,让其仅对感兴趣的Bean进行加工处理
        4.工厂后处理器接口方法:
             包括AspectJWeavingEnable、CustomerAutowireConfigurer、ConfigurationClassPostProcessor等方法。
             工厂后处理器也是容器级的,在应用上下文装配配置文件后立即调用


             
2.ApplicationContext中Bean的生命周期


    1、Bean在应用上下文中的生命周期与在BeanFactory中类似,不同的是在第一步前如果配置了工厂后处理器接口BeanFactoryPostProcessor
       的实现类,则在应用上下文加载配置后,初始化Bean实例之前将调用这些BeanFactoryPostProcessor对配置信息进行加工处理。
       工厂后处理器是容器级的,仅在应用上下文初始化时调用一次,其目的是完成一些配置文件的加工处理工作
    2.如果Bean实现了org.springframework.context.ApplicationContextAware接口,则会在第八步setBeanFactory后
      调用setApplicationContext方法
    3.ApplicationContext与BeanFactory的另一个最大不同是:
        ApplicationContext会利用java反射机制自动识别出配置文件中定义的BeanPostProcessor、InstantiationAwareBeanPostProcessor
        和BeanFactoryPostProcessor,并自动将它们注册到上下文中
        BeanFactory则在代码中通过手工调用addBeanPostProcessor()方法进行注册
  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章