相信大多数初级程序员在面试的时候都面试过Spring中bean的生命周期,大多数人对其不太了解,认为周期一般都是: 初始化->使用->销毁就行了,Spring对bean的管理增加了很多操作,所以Spring中bean的生命周期上涉及的内容就比较多了,本文写个简单的例子来说明一下。
本文只是举例介绍下,具体源码讲解在下一篇:Spring源码分析之Bean的生命周期(二)
public class User implements InitializingBean {
private String name;
private int age;
User(){
System.out.println("User Constructor");
}
public void init(){
System.out.println("User Init");
}
public void destroy(){
System.out.println("Destroy Method");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("User setName");
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("User afterPropertiesSet");
}
}
public class MyBeanPostProcessor implements BeanPostProcessor {
MyBeanPostProcessor(){
System.out.println("MyBeanPostProcessor Constructor");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor -> BeforeInitialization :"+bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor -> AfterInitialization :"+bean);
return bean;
}
}
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
MyBeanFactoryPostProcessor(){
System.out.println("MyBeanFactoryPostProcessor Constructor");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition userDefinition = beanFactory.getBeanDefinition("user");
MutablePropertyValues propertyValues = userDefinition.getPropertyValues();
propertyValues.addPropertyValue("age",10);
System.out.println("BeanFactoryPostProcessor -> postProcessBeanFactory");
}
}
XML中的配置
<bean id="user" class="com.jack.User" init-method="init" destroy-method="destroy">
<property name="name" value="JACK">property>
bean>
<bean class="com.jack.MyBeanPostProcessor">bean>
<bean class="com.jack.MyBeanFactoryPostProcessor">bean>
测试代码:
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:beans.xml");
User user = (User) applicationContext.getBean("user");
System.out.println("user=" + user);
//这段代码是必须的,当关闭容器的时候会销毁Bean
((ClassPathXmlApplicationContext) applicationContext).close();
}
上面代码中有两个类BeanPostProcessor与BeanFactoryPostProcessor说一下:
这两个类都是后置处理器,其中BeanPostProcessor是Bean对象的后置处理器,主要用来对实例化的bean对象做处理,而BeanFactoryPostProcessor是Bean工厂的后置处理器,Bean工厂内部管理的主要是BeanDefinition,所以它一般用来做对BeanDefinition的处理,在这里可以修改XML中的配置结果,例如给属性设置值,修改对象的单例。正常思考一下BeanFactoryPostProcessor肯定要执行在BeanPostProcessor之前,因为先有工厂再有实例,并且先有模板再有对象,前者操作的是模板,如果先有了对象了改模板就没有意义了。
执行结果从上往下看:
默认情况下Spring使用的是饿汉式单例设计模式,在容器初始化的时候就做了Bean的初始化操作,如果是懒加载的也就是懒汉式设计模式和非单例的会在getBean()的时候执行Bean的初始化操作。
正常情况下我们认为生命周期也就是Init -> Use -> Destroy,Spring在Bean的生命周期中增加了N多步操作,对我们来讲是没有多大意义的,但是对构建Spring的其他框架来说有着重要的意义,因为其他框架中可能涉及到对Bean的一些处理需要精细到每一步操作,例如看一下BeforeInit和AfterInit是不是比较熟悉,这和我们学的AOP有点相似,没错这里可能创建的类可能在其他框架中需要动态代理,所以加了PostProcess类的操作。
整个Bean初始化操作周期具体执行的源代码在这一步:
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
而XML中的bean配置转换为BeanDefinition的操作在初始化Bean工厂的时候执行的:
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
这两个代码都是在加载配置文件中的refresh()方法中,不管是那种bean注入方式都会调用refresh()方法,这可以说是Spring中比较复杂的代码了,涉及的内容比较多,有耐心的可以自己看一下:
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
这里面有几个误解的地方需要注意一下: