1. 前言
本文主要記錄一下Spring中bean的生命周期绑警,即從bean實(shí)例化到最終銷毀的過(guò)程中一些重要的節(jié)點(diǎn)姊氓,以及Spring提供的在bean這些節(jié)點(diǎn)過(guò)程中的一些操作在讶。
2. Bean生命周期
如下圖所示:
2.1 BeanFactoryPostProcessor
該接口有如下方法:
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
該接口的實(shí)現(xiàn)類最先被實(shí)例化名挥,它是一個(gè)spring容器級(jí)別的后置處理器瓮顽,盡管此時(shí)所有的bean都沒(méi)有被實(shí)例化出來(lái),但是bean的配置文件已經(jīng)被分析完围橡,所有的bean的定義信息(spring中使用類BeanDefinition表示)已經(jīng)加載暖混,可以通過(guò)ConfigurableListableBeanFactory # getBeanDefinition(String beanName)
獲取,獲取到BeanDefiniton意味著你可以修改bean的屬性了翁授。
BeanFactoryPostProcessor 的一些實(shí)現(xiàn)類
- PropertyPlaceholderConfigurer
這個(gè)很多人用過(guò)拣播,從key=value形式的配置文件中加載配置信息晾咪,并通過(guò)${propertyName}的形式設(shè)置到bean屬性上,如下面這種形式:
<context:property-placeholder
location="classpath:db.properties"
file-encoding="utf8"
/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.user}"/>
<property name="password" value="${db.password}"/>
</bean>
注:上面使用了簡(jiǎn)易的形式<context:property-placeholder .../>, 這種情況下會(huì)創(chuàng)建PropertyPlaceholderConfigurer
對(duì)應(yīng)的bean贮配。關(guān)于<context>命名空間谍倦,請(qǐng)看 附錄1
- PropertyOverrideConfigurer
這個(gè)和PropertyPlaceholderConfigurer
一樣將bean的屬性卸載properties文件中,用法如下:
首先假設(shè)在db.properties中如下內(nèi)容:
dataSource.username=root
dataSource.password=root
同樣是name=value的形式泪勒,但是name必須是<beanName>.<beanPropertyName>格式
然后在applicationContext.xml中如下定義bean即可:
<!--這個(gè)命名空間會(huì)加載PropertyOverrideConfigurer-->
<context:property-override location="db.properties"/>
<!--bean id需要和db.properties中beanName一樣-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
</bean>
PropertyOverrideConfigurer這個(gè)后置處理器會(huì)根據(jù)db.properties中dataSource這個(gè)bean的名字找到屬性昼蛀,然后填充到dataSource這個(gè)bean中
2.2.2 BeanPostProcessor
BeanPostProcessor有兩個(gè)接口方法:
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
BeanPostProcessor在普通bean實(shí)例化之前就就創(chuàng)建了,但是他的兩個(gè)接口方法在卻在普通bean實(shí)例化(即創(chuàng)建bean類的對(duì)象)圆存,通過(guò)setter完成了屬性注入之后調(diào)用叼旋,這兩個(gè)方法在bean初始化前后調(diào)用(bean初始化是指調(diào)用xml中bean定義中init-method指定的方法,或者bean實(shí)現(xiàn)了InitializingBean接口沦辙,調(diào)用接口方法)夫植,詳細(xì)的可見(jiàn)上圖。
BeanPostProcessor的一些實(shí)現(xiàn)類
- AutowiredAnnotationBeanPostProcessor
用于使用@Autowired
和@Value
注解的解析 - RequiredAnnotationBeanPostProcessor
用于使用@Require
注解的解析 - CommonAnnotationBeanPostProcessor
用于使用@Resource
,@PostConstruct
,@PreDestroy
注解的解析油讯。
上面三類在在基于注解的方式裝配bean時(shí)經(jīng)常使用详民,當(dāng)在xml文件里配置
<context:annotation-config />
時(shí),spring會(huì)創(chuàng)建上面三類PostProcessor陌兑,同樣輸入context空間沈跨,參考 附錄1
- ScheduledAnnotationBeanPostProcessor
用于使用了@Scheduled
注解的方法的解析,在xml中添加<task:annotation-driven>
時(shí)會(huì)創(chuàng)建這個(gè)PostProcessor, 如下例所示:
<beans>
<task:annotation-driven scheduler="taskScheduler"/>
<task:scheduler id="taskScheduler" pool-size="42"/>
<task:scheduled-tasks scheduler="taskScheduler">
<task:scheduled ref="myTask" method="work" fixed-rate="1000"/>
</task:scheduled-tasks>
<bean id="myTask" class="com.foo.MyTask"/>
</beans>
這個(gè)例子來(lái)自于spring代碼@EnableScheduling注釋
2.2.3 ApplicationContextAware
它只有一個(gè)接口方法setApplicationContext(ApplicationContext apc)
, 實(shí)現(xiàn)它的bean而言诀紊,apc即該bean運(yùn)行時(shí)所處的applicationContext谒出,上圖沒(méi)有畫(huà)出它的調(diào)用時(shí)機(jī),它在BeanFactoryAware # setBeanFactory
之后調(diào)用邻奠。
實(shí)現(xiàn)ApplicationContextAware的類
- EventListenerMethodProcessor
spring中事件機(jī)制中笤喳,用來(lái)處理bean中使用了@EventListener
標(biāo)注成事件接收這個(gè)的method。
關(guān)于事件機(jī)制參考spring 事件機(jī)制
附錄1 - context命名空間
在spring-context
的jar包中META-INF目錄下有文件‘spring.handlers’中有這樣一行http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
, context命名空間加載了類ContextNamespaceHandler
碌宴,下面是這個(gè)類的init方法:
@Override
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
包含了context這個(gè)命名空間下所有子元素對(duì)應(yīng)的Parser, 這寫(xiě)parser負(fù)責(zé)解析xml元素杀狡,然后創(chuàng)建對(duì)應(yīng)BeanDefinition