SpringIOC容器它会以某种方式,加载配置文件中的 信息,将其解析为一个个的BeanDefinition.之后将BeanDefinition注册到容器之中。Spring IOC容器在实现的时候经过的过程可以使用如下图片表示:
分为两个主要部分:
其一 :容器启动阶段
其二:bean实例化阶段。
在容器的启动阶段主要做的是一些信息收集的过程(主要依赖于工具类BeanDefinitionReader),将收集的信息组成BeanDefinition.将BeanDefinition注册到相应的BeaneanRegistry.
Bean实例化的过程在请求方通过容器的getBean方法明确请求某个对象时候触发/隐式依赖关系调用时候也会触发该动作。此阶段做的操作主要是判断当前的请求对象是否已经被实例化过了。根据情况进行注入。当该对象实现某些回调接口。也会根据回调函数接口装配它
容器的前置处理 BeanFactoryPostProcess:
此后内容主要是对于容器实现第一阶段进行处理。Spring提供了容器扩展机制BeanFactoryPostProcess。这个机制允许我们在实例化相应对象之前对注册到容器中的BeanDefinition的存储信息进行修改。可以根据这个机制对Bean增加其它信息。修改Bean定义的某些属性值。
想自定义前置处理器需要实现BeanFactoryPostProcess
接口。当一个容器存在多种前置处理的时候,可以让前置处理器的实现类同时继承Ordered
接口。
Spring容器提供了数种现成的前置处理器,常见的如:
PropertyPlaceholderConfigurer
:允许在xml文件中使用占位符。将占位符代表的资源单独配置到简单的Properties文件中加载PropertyOverrideConfigurer
:不同于PropertyPlaceholderConfigurer的是,该类用于处理容器中的默认值覆为新值的场景CustomEditorConfigurer
:此前的两个前置处理器处理的均是BeanDefinition.通过把BeanDefinition的数据修改达到目的。CustomEditorConfigurer没有对BeanDefinition做任何变动。负责的是将后期会用到的信息注册到容器之中。例如将类型转换器注册到BeanDefinition中。供BeanDefinition将获取到的String类型参数转换为需要的类型。
装配前置处理器
装配前置处理器分为两种情况。一种是普通的BeanFactory.一种是ApplicationContext.对于ApplicationContext可以自动识别并装配前置处理器。
ApplicationContext的装配可以直接用xml文件实现:
配置文件:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>propertyHolder.properties</value>
</list>
</property>
</bean>
代码:
ApplicationContext factory=new ClassPathXmlApplicationContext("simple.xml");
启动的时候自动装载前置增强bean。无须额外操作。
BeanFactory装配方式:
ConfigurableListableBeanFactory factory=new XmlBeanFactory(new ClassPathResource("simple.xml"));
PropertyPlaceholderConfigurer configurer=new PropertyPlaceholderConfigurer();
configurer.setLocation(new ClassPathResource("propertyHolder.properties"));
configurer.postProcessBeanFactory(factory);
三种前置处理器
1.PropertyPlaceholderConfigurer前置处理器
应用场景:
不想将系统管理相关的业务配置信息混杂到XML文件中的时候,可以将文件配置到properties.如此可以在当系统参数发生变幻时候,只需修改properties配置文件。强化可读性的同时,也降低了维护难度。
代码:
配置文件
<bean id="propertyHolder" class="com.example.demo.postprocess.MyPropertyHolderBean">
<property name="username">
<value>${java.version}</value>
</property>
<property name="password" value="${propertyHold