zoukankan      html  css  js  c++  java
  • Spring IoC容器实现

    1,Spring的两种IoC容器

    BeanFactory 

    • 基础类型的IoC容器;
    • 采用延迟初始化策略(容器初始化完成后并不会创建bean的对象,只有当收到初始化请求时才进行初始化);
    • 由于延迟初始化,因此启动速度较快,占用资源较少;

    ApplicationContext 

    • 在BeanFactory的基础上,增加了更为高级的特定:事件发布、国际化等;
    • 在容器启动时便完成所有bean的创建;
    • 启动时间较长,占用资源更多;

    2,IoC容器的主要类/接口介绍

    1)BeanFactory 
    它是一个接口,提供了获取容器中Bean的相关方法。

    2)BeanDefinitionRegistry 
    它才是IoC的容器,用于存储、管理所有的Bean对象。

    3)DefaultListableBeanFactory 
    它是IoC容器的一个具体实现,实现了BeanFactory和BeanDefinitionRegistry接口,因此既拥有管理Bean的容器,又拥有访问Bean的方法。

    4)BeanDefinition 
    每一个Bean都有一个BeanDefinition与之对应,用于存储Bean的相关信息:对象的class类型、是否是抽象类、构造方法参数等。 

    RootBeanDefinitionChildBeanDefinition是BeanDefinition的两个主要的实现类。

    5)BeanDefinitionReader 

    在Spring中,标注Bean的依赖关系有四中方式:

      1. 直接在代码中声明
      2. 通过XML文件声明
      3. 通过Properties文件声明
      4. 通过注解声明 
        BeanDefinitionReader接口的作用就是读取配置文件中的bean信息,把它们解析成BeanDefinition对象,然后注册到BeanDefinitionRegistry中去。 
        PropertiesBeanDefinitionReader和XmlBeanDefinitionReader是该接口的两个实现类,分别用于解析properties和xml格式的配置文件。

    6)XmlBeanFactory 
    它是一个集成了XmlBeanDefinitionReader功能的BeanFactory,用于简化初始化操作。

    3,BeanFactory的两个重要阶段

    容器启动阶段 

    该阶段Spring会使用BeanDefinitionReader加载配置文件,并把所有的bean解析成BeanDefinition对象,并注册到BeanDefinitionRegistry

    Bean实例化阶段 

    对于BeanFactory容器,当调用者主动调用getBean方法或者因存在依赖关系容器隐式调用getBean时,如果当前Bean尚未初始化,或者bean配置成prototype,就会触发Bean实例的初始化

    4,BeanFactoryPostProcessor:一种容器扩展机制

    Spring提供了BeanFactoryPostProcessor这种容器扩展机制,它允许我们在容器启动完成后Bean实例化前插入额外的操作。 

    BeanFactoryPostProcessor提供了三个实现类:

    1.PropertyPlaceholderConfigurer 
      一般情况下,我们并不会将数据库连接信息直接写死在dataSource这个bean中,而是将它们单独写在一个properties文件中,这样易于修改与阅读。而bean中使用占位符代替这些属性值,当容器启动完成后,在Bean初始化前用properties文件中的值替换占位符,再创建对象。 
    PropertyPlaceholderConfigurer就能实现这样的功能。

    • xml中作如下配置:
    <bean id="dataSource" class="xxxxxx">
        <property name="url">
            <value>${jdbc.url}</value>
        </property>
        <property name="username">
            <value>${jdbc.username}</value>
        </property>
    </bean>
    • 使用properties文件存储属性值:
    jdbc.url=jdbc:mysql://127.0.0.1:3306
    jdbc.username=root

    当容器启动完成后dataSource的BeanDefinition对象将会被注册进BeanDefinitionRegistry中,此时BeanDefinition中的属性值仍然是占位符的形式;接下俩,PropertyPlaceholderConfigurer就会发挥作用,它会将占位符用properties文件中的属性值替换掉。接下来bean就可以被正确地创建。

    2.PropertyOverrideConfigurer 
    它的功能与PropertyPlaceholderConfigurer类似,也需要指定一个properties文件,只不过它会用配置文件中设置的那些bean的属性值替换指定bean的属性值。

    • xml中作如下配置:
    <bean id="dataSource" class="xxxxxx">
        <property name="url">
            <value>jdbc:mysql://127.0.0.1:3306</value>
        </property>
        <property name="username">
            <value>chai</value>
        </property>
    </bean>
    • 使用properties文件存储属性值:
    dataSource.url=jsbc:mysql://127.0.0.1:3307
    dataSource.username=root

    PropertyOverrideConfigurer会在容器启动完毕后、Bean对象创建之前,通过修改BeanDefinition对象,替换指定的属性值。 
    properties文件的内容必须遵循如下格式:

    bean的名字.属性名=属性值

    3.CustomEditorConfigurer 

    该类用于向Spring容器增添自定义的PropertyEditor对象。

      容器启动结束后bean创建之前,配置文件中所有的bean都被解析成BeanDefinition对象,该对象中关于bean所有的信息都是String类型的,若要创建bean对象,就需要将这些String类型的信息解析成它们原本的类型。在Spring中,每种类型都有对应一个PropertyEditor类,该类中封装了String与该类型的转换方法。当然,对于某些类型Spring并未提供相应的PropertyEditor时,我们可以自定义PropertyEditor,并使用CustomEditorConfigurer将其告诉Spring容器,让它在遇到该类型的时候采用我们自定义的PropertyEditor去解析。

    Spring提供的部分PropertyEditor:

      • StringArrayPropertyEditor 
        将字符串转换成String[],默认以,分割。
      • ClassEditor 
        类似于Class.forname(String),将字符串转换成class对象。
      • FileEditor 
        将字符串转换成File对象。
      • URLEditor 
        将字符串转换成URL对象。
      • InputStreamEditor 
        将字符串转换成InputStream对象。
      • LocaleEditor 
        将字符串转换成Locale对象。
      • PatternEditor 
        将字符串转换成Pattern对象。

    以上类型的字符串,Spring会自动将它们转换成原本的类型。而我们自定义的PropertyEditor必须要通过CustomEditorConfigurer将其加入容器。

    如何开启BeanFactoryPostProcessor功能? 
    1.BeanFactory

    // 创建BeanFactory对象
    ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory( new ClassPathResource("xxx") );
    // 创建BeanFactoryPostProcessor对象
    PropertyPlaceholderConfigurer processor = new PropertyPlaceholderConfigurer();
    // 设置properties文件的位置
    processor.setLocation("xxx");
    // 将其传递给beanFactory
    processor.postProcessBeanFactory(beanFactory);

    2.ApplicationContext 
    ApplicationContext会自动检测配置文件中出现的BeanFactoryPostProcessor,因此只需要在配置文件中声明所使用的BeanFactoryPostProcessor即可。

    <bean class="xxxxx.PropertyPlaceholderConfigurer">
        <property>
            <list>
                <value>properties文件路径</value>
            </list>
        </property>
    </bean>

    https://blog.csdn.net/u010425776/article/details/55269888

  • 相关阅读:
    2018 ICPC南京网络赛 A An Olympian Math Problem(数论题)
    算法竞赛模板 素数测试(Miller-Rabin测试)
    算法竞赛模板 tarjan算法
    2018 CCPC网络赛 1004 Find Integer(勾股数+费马大定理)
    算法竞赛模板 概率dp
    算法竞赛模板 重载运算符
    算法竞赛模板 矩阵快速幂
    算法竞赛模板 回文素数
    算法竞赛模板 AC自动机
    算法竞赛模板 拓扑排序
  • 原文地址:https://www.cnblogs.com/xdyixia/p/9350930.html
Copyright © 2011-2022 走看看