上一篇温习了Spring实例化bean的三种方式,接下来我们继续温习一下Spring的基础知识Bean的生命周期,在了解Bean的生命周期之前应该对Bean的作用域有所了解。
了解bean的生命周期对于接下来要分析源码非常重要,而且面试经常会问到spring的生命周期
Bean factory implementations should support the standard bean lifecycle interfaces as far as possible. The full set of initialization methods and their standard order is:
1.BeanNameAware's setBeanName
2.BeanClassLoaderAware's setBeanClassLoader
3.BeanFactoryAware's setBeanFactory
4.EnvironmentAware's setEnvironment
5.EmbeddedValueResolverAware's setEmbeddedValueResolver
6.ResourceLoaderAware's setResourceLoader (only applicable when running in an application context)
7.ApplicationEventPublisherAware's setApplicationEventPublisher (only applicable when running in an application context)
8.MessageSourceAware's setMessageSource (only applicable when running in an application context)
9.ApplicationContextAware's setApplicationContext (only applicable when running in an application context)
10.ServletContextAware's setServletContext (only applicable when running in a web application context)
11.postProcessBeforeInitialization methods of BeanPostProcessors
12.InitializingBean's afterPropertiesSet
13.a custom init-method definition
14.postProcessAfterInitialization methods of BeanPostProcessors
On shutdown of a bean factory, the following lifecycle methods apply:
1.postProcessBeforeDestruction methods of DestructionAwareBeanPostProcessors
2.DisposableBean's destroy
3.a custom destroy-method definition
都是英文,而且都是spring内部接口或者类,方法的使用,再用图片来说明一下
在前面的博客中我们已经分析了Spring容器的启动,只是一个开端,接下来要分析的东西才是重点和难点…如果对Spring生命周期毫无了解的人,这张图令人费解,接下来我们简单分析一下图中的流程,每个步骤的作用,再通过一个简单的例子,让大家对bean的生命周期有所了解
到此为止,bean的实例化到销毁过程,就是整个bean的生命周期了。下面来看一个实际的例子:
package com.lyc.cn.day02;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class MyLifeCycleBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
// 姓名
private String name;
// 年龄
private int age;
@Override
public void setBeanName(String name) {
System.out.println("01-->BeanNameAware接口被调用了, 获取到的beanName:" + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("02-->BeanFactoryAware接口被调用了");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("03-->ApplicationContextAware接口被调用了");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("05-->InitializingBean接口被调用了");
}
public void myInit() {
System.out.println("06-->myInit方法被调用了");
}
@Override
public void destroy() throws Exception {
System.out.println("09-->DisposableBean接口被调用了");
}
public void myDestroy() {
System.out.println("10-->自定义destroy-method方法被调动了");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "MyLifeCycleBean{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
package com.lyc.cn.day02;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("04-->调用postProcessBeforeInitialization方法, 获取到的beanName: " + beanName);
((MyLifeCycleBean) bean).setName("李四");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("07-->调用postProcessAfterInitialization, 获取到的beanName: " + beanName);
((MyLifeCycleBean) bean).setAge(30);
return bean;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--注意:这里配置的name是张三,age是25,我们会通过beanPostProcessor来修改nage和age -->
<bean id="myLifeCycleBean" name="myLifeCycleBean1,myLifeCycleBean2" class="com.lyc.cn.day02.MyLifeCycleBean" destroy-method="myDestroy"
init-method="myInit">
<property name="name" value="张三"/>
<property name="age" value="25"/>
</bean>
<bean id="myBeanPostProcessor" class="com.lyc.cn.day02.MyBeanPostProcessor"/>
</beans>
package com.lyc.cn.day02;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyLifeCycleBeanTest {
@Before
public void before() {
System.out.println("---bean生命周期开始---\n");
}
@After
public void after() {
System.out.println("\n---bean生命周期结束---");
}
/**
* 生命周期测试
*/
@Test
public void testDefaultConstructor() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("day02.xml");
MyLifeCycleBean myLifeCycleBean = applicationContext.getBean("myLifeCycleBean", MyLifeCycleBean.class);
System.out.println("08-->bean可以被使用了, beanInfo: " + myLifeCycleBean.toString());
((ClassPathXmlApplicationContext) applicationContext).destroy();
}
}
---bean生命周期开始---
01-->BeanNameAware接口被调用了, 获取到的beanName:myLifeCycleBean
02-->BeanFactoryAware接口被调用了
03-->ApplicationContextAware接口被调用了
04-->调用postProcessBeforeInitialization方法, 获取到的beanName: myLifeCycleBean
05-->InitializingBean接口被调用了
06-->myInit方法被调用了
07-->调用postProcessAfterInitialization, 获取到的beanName: myLifeCycleBean
08-->bean可以被使用了, beanInfo: MyLifeCycleBean{name='李四', age=30}
09-->DisposableBean接口被调用了
10-->自定义destroy-method方法被调动了
---bean生命周期结束---
可以看到,bean的生命周期按照我们刚才的分析一步一步的执行,并通过MyBeanPostProcessor中的方法修改了name和age属性,xml配置文件:name:张三,age:25程序输出的是name:李四,age:30。