spring bean生命周期学习

第一章 IoC容器

IoC定义:Inverse of Control 控制反转。将new接口实现类的权利交到第三方类(导演类)中。导演类负责实例化接口的实现类,然后注入到依赖类中。

类加载器和反射。通过反射的方式可以将配置文件中定义字符串变成类的实例(先通过全名限定,利用类加载器加载类进jvm),然后根据依赖关系注入到其他类中。

资源访问接口
    ——Resource接口的不同实现类负责从不同类型资源文件中加载资源。ResourceLoader资源加载器及其实现类PathMatchingResourcePatternResolver负责根据资源地址前缀和路径通配符加载资源。
    ——有了上述接口,spring容器将可以方便的加载配置文件中定义的bean信息,从而实现控制反转。

IoC容器:BeanFactory和ApplicationContext   ApplicationContext基于BeanFactory两个容器在启动的时候必须初始化日志框架例如:log4j。不然spring启动将出错。

BeanFactory
    ——BeanFactory作为IoC容器的核心接口,通过不断的扩展性形成了一套继承体系。这套体系可以让开发者从不同层面使用容器。
    ——ConfigurableBeanFactory等接口可以为容器添加定制化的功能。例如:在bean生产的过程中添加一系列处理器,以增强bean的实例化过程。
    ——BeanFactory目前的实现类只有DefaultListableBeanFactory 而 XmlBeanFactory已经被废弃。
    ——XmlBeanDefinitonReader负责将配置文件的bean定义解析为BeanDefiniton类,为BeanFactory提供信息。ClassPathXmlApplicationContext中已经具备该能力。
    ——AnnotationConfigApplicationContext具备从java配置类中启动的能力。WebApplicationContext具备从web根路径启动的能力。WebApplicationContext中需引用ServletContext,同时自身也作为ServletContext属性,通过ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE键被引用
    ——Web环境中初始化WebApplicationContext有2中方式:自启动Servlet和ContextLoaderListen。低版本Servlet不支持监听的方式启动。启动只需在web中配置即可。
 
BeanFactory的生命周期
    1. 生命周期过程: getBean()过程
        ——调用postProcessBeforeInstatiation()方法   1
        ——调用bean的构造器
        ——调用postProcessAfterInstantiation()方法   1
        ——调用postProcessProptertyValues()方法      1
    ——调用bean的属性器设置属性(注入配置文件中定义的属性依赖)
    ——调用setBeanName()方法                2
        ——调用setBeanFacotry()方法              2
        ——调用postProcessBeforeInitialization()方法 3
        ——调用afterPropertiesSet()方法          2
        ——调用init-method配置的初始化方法
        ——调用postProcessAfterInitialization()方法  3
        ——单例放入容器的缓冲池中。prototype交给调用者
        ——调用destroy()方法                  2
        ——调用destroy-method配置的销毁方法    
            ——整个生命周期中:1为容器级的处理器(InstantiationAwareBeanPostProcessor接口),负责处理所有bean的共性问题;2为bean级的处理器,定义在bean自身类中(通过实现BeanNameAware、BeanFactoryAware、InitializingBean、DisposableBean接口);3为容器级的处理器(BeanPostProcessor接口)。
          ——其中InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口。通过ConfigurableBeanFactory.addBeanPostProcess()方法可以将自定义的处理器加入到beanFactory中。
             ——容器在创建的过程中会检查这些接口,然后做相应处理。
        ——从上述生命周期过程可以看出,核心过程为调用bean的构造器,属性器,初始化方法,销毁方法的过程。各处理器为spring框架生命周期接口提供的额外控制。但使用spring不应对应用程序类做任何限制。所以一般不会注册这些处理器。AOP和注解例外。

ApplicationContextd的生命周期
    ——其生命周期与BeanFactory基本一致。
    ——在ApplicationContext启动的时候(<bean>被解析为BeanDefiniton时)可以注册BeanFactoryPostProcessor处理器,并调用postProcessBeanFactory()方法以对配置文件进行处理。该处理器可以直接在配置文件中声明实现了对应接口的bean来注册。


第二章:在IoC容器中装配Bean
Bean定义注册表:将配置中的bean定义加载进spring,通过id和BeanDefiniton描述。多个BeanDefinition形成了注册表

基于XML的配置
    ——spring2.0以后采用Schema格式的配置
    ——xmlns为默认的命名空间 一般为bean
    ——xmlsn:aop为aop指定命名空间,aop为命名空间的别名
    ——xmlns:xsi为xsi指定命名空间,然后可以通过xsi为所有命名空间指定xsi文件url
    ——xsi:schemaLocation通过xsi别名配置各命名空间的schema文件。

Bean的基本配置
    ——通过id和name为Bean命名,id全局唯一、不含特殊字符。name例外,但是同名将覆盖。
    ——依赖注入
        ——属性注入:配置<property name=><value></省略></>将通过反射寻找setXXX()方法注入。属性名前两个字母要么全大写要么全小写。    
        ——构造器注入:<construction-arg index= type= ref=><value></></>多相似构造器下使用index和type唯一确定。ref引用其他bean
    ——工厂方法注入:<bean factory-bean="" factory-method=""/> 需先声明factory-bean这个Bean。
    ——静态工厂方法注入 <bean class="" factory-method="">
    ——<value>标签注入字面值 <![CDATA[...]]>让XML将里面字符当普通字符处理。没有值则为""字符串
    ——<bean/>将在属性中注入一个bean
    ——<ref parent="">引用父容器中的bean
    ——<null/>将注入Null
    ——<property name="class.property...">可以配置级联属性,不过必须在当前类里面有一个class的实例。
    ——<property name=""><list><value></></></>可以为list直接注入值。同理<set>也是一样,不过类中必须先有一个实例化的对象。
    ——<property name=""><list><entry><key><value></></><value></></></></>为map注入值。
    ——<prperty name=""><props><prop key="">sadf</><prop></></>方式为properties注入。只能注入字符串类型。
    ——通过util命名空间配置集合类型的bean
    ——<utils:list id="" list-class="java.util.LinkedList"><value></></util:list> map类型为<entry key="" value=""/><entry />
    ——使用p命名空间
    ——原来的使用property标签可以直接改为 p:name="小明" p:car-ref="car"设置属性和引用。


第三章:ApplicationContext

初始化步骤
    1. 初始化BeanFactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    2. 调用工厂后处理器BeanFactoryPostProcessor 在BeanDefinition中找出实现此接口的Bean用来对BeanDefinition中未完成的Bean进行加工.
    3. 注册bean后处理器 BeanPostProcess用于对bean实例化进行加工
    4. 初始化消息源
    5. 初始化应用上下文事件广播器
    6. 初始化其他特殊的Bean   onFresh()
    7. 注册事件监听器
    8. 初始化所有单实例的Bean,使用懒加载模式的Bean除外
    9. 完成刷新并发布容器刷新事件。

BeanDefinition: 配置文件中<bean>标签解析后生成的对象,被注册到BeanDefinitionRegistry中。初步生成的BeanDefinition可能只是半成品,需要BeanFactoryPostProcessor对其进行加工。
来解析占位符为最终的实际值。

InstantialtionStrategy 通过不同策略实例化bean, 尚未设置属性

BeanWrapper 为Bean设置属性。主要通过属性编辑器来设置属性,通过BeanWrapper接口进行访问。


属性编辑器:
——PropertyEditorRegistrySupport为常见的类型提供了默认的属性编辑器。 注册属性编辑器:defaulEditors.put(char.class, new CharacterEditor(false));

——如果需要对复合类型进行转换需要自定义的属性编辑器。可以通过扩展PropertyEditorSupport类来实现自己的属性编辑器(覆盖 void setAsText(String text) 定义自定义解析器,然后调用父类setValue()设置转换后的属性),然后添加到注册map中。
CustomerEditorConfigurer类实现了工厂后处理器,将在spring初始化的时候,自动调用。所以只需在其customEditors属性中,加入自定义的编辑器类即可。
<bean class= "org.springframework.beans.factory.config.CustomEditorConfigurer">
    <property name = "customEditors">
       <map>
             <entry key = "com.xx.Xxx" value= "com.xxx.xxx.CustomXxxEditor">          
             </entry>
       </map>
    </property>
</bean>
这样就可以为某个类型注册一个属性编辑器,直接在配置文件中按照自定义格式设置字面值,属性编辑器会解析成对应复合类型。
  
——使用外部属性文件: PropertyPlaceholderConfigurer在对属性进行转换的时候,会去外部文件寻找值进行占位符替换。
该类实现了BeanFactoryPostProcessor接口在spring容器初始化的时候将自定调用(postProcessBeanFactory方法,在该方法中调用convertProperty方法设置属性值。)以完善BeanDefiniton对象的内容。
<bean class = "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
      p:location = "classpath:com/smart/placeholder/jdbc.properties">
        p:fileEncoding = "utf-8" /> 可在该类中指定外部属性文件的地址和编码方式
或者:
<context:property-placeholder location="classpath:com.smart.jdbc.properties">

在其父类中PropertyResourceConfigurer类中,convertProperty(propertyName, propertyValue)用于在属性使用之前对属性值进行转换处理。可以用来对密码等属性进行加解密。

——应用其他bean的值:
#{beanName.beanproperty}可以直接引用其他bean中的属性值。

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