spring之一 bean初始化
spring bean生命周期
- Bean容器找到配置文件中Spring Bean的定义。
- Bean容器利用Java Reflection API创建一个Bean的实例。
- 如果涉及到一些属性值 利用set方法设置一些属性值。
- 如果Bean实现了BeanNameAware接口,调用setBeanName()方法,传入Bean的名字。
- 如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
- 如果Bean实现了BeanFactoryAware接口,调用setBeanClassLoader()方法,传入BeanFactory。
- 与上面的类似,如果实现了其他*Aware接口,就调用相应的方法。
- 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessBeforeInitialization()方法
- 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
- 如果Bean在配置文件中的定义包含init-method属性,执行指定的方法。
- 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessAfterInitialization()方法
- 当要销毁Bean的时候,如果Bean实现了DisposableBean接口,执行destroy()方法。
- 当要销毁Bean的时候,如果Bean在配置文件中的定义包含destroy-method属性,执行指定的方法。
根据代码debug来看spring是怎么初始化一个bean的,先简单写一个service,代码如下
package com.spring.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class CountryService implements InitializingBean{
Logger logger = LoggerFactory.getLogger(CountryService.class);
public String getCountry(){
return "china";
}
public CountryService() {
logger.info("construct");
}
@Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
logger.info("afterPropertiesSet");
}
}
bean配置文件bean-definition.xml如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang.xsd">
<bean id="countryServiceBean" abstract="false"
class="com.spring.service.CountryService">
</bean>
</beans>
CommonBeanPostProcessor代码如下
package com.spring.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class CommonBeanPostProcessor implements BeanPostProcessor{
Logger logger = LoggerFactory.getLogger(CommonBeanPostProcessor.class);
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
logger.info("postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
logger.info("postProcessAfterInitialization");
return bean;
}
}
测试文件如下
package com.spring;
import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import com.spring.service.CommonBeanPostProcessor;
public class XmlDefinitionTest {
static Logger logger = LoggerFactory.getLogger(XmlDefinitionTest.class);
public static void main(String args[]){
Resource xmlResource = new ClassPathResource("bean-definition.xml");
XmlBeanFactory beanFactory = new XmlBeanFactory(xmlResource);
Iterator<String> beanNameIt= beanFactory.getBeanNamesIterator();
beanFactory.addBeanPostProcessor(new CommonBeanPostProcessor());
while(beanNameIt.hasNext()){
String beanName = beanNameIt.next();
Object object = beanFactory.getBean(beanName);
logger.info(object.toString());
}
}
}
然后在getBean那一行再打个断点,调用栈如下图
在initializeBean方法中首先调用invokeAwareMethods方法,这个方法的内容对应bean声明周期中的
- 如果Bean实现了BeanNameAware接口,调用setBeanName()方法,传入Bean的名字。
- 如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
- 如果Bean实现了BeanFactoryAware接口,调用setBeanClassLoader()方法,传入BeanFactory
接下来调用applyBeanPostProcessorsBeforeInitialization方法,对应于bean声明周期中的
如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessBeforeInitialization()方法
然后调用invokeInitMethods方法,具体如下
对应bean声明周期中的
- 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
- 如果Bean在配置文件中的定义包含init-method属性,执行指定的方法。
然后再调用postProcessAfterInitialization方法,对应bean生命周期中的
如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessAfterInitialization()方法
到此一个bean就实例化完成,然后就可以使用了。
查看程序执行结果