Hello,大家好,上一篇Spring系列的文章给大家讲了Spring容器的一些知识,然后讲了核心的WebApplicationContext的初始化,这一节准备给大家讲解Spring 容器中的Bean的生命周期。这一节我个人觉得还是比较实用的,在实际工作当中经常会用到这些知识来解决一些非常棘手的问题。好了,老套路,文章结构:
先来张图:
大家看到这张图肯定是一脸蒙蔽。不要着急,我来慢慢解释:从getBean(...)为触发点,Spring容器的Bean生命周期就经历了图中的生命周期,先分个类:
值得一提的是,无论是" 容器级后处理器 "还是" 工厂级后处理器 ",他们都是可以配置多个的(如,配置两个BeanPostProcessor),如果想控制他们的调用顺序,实现一个org.springframework.core.Ordered接口即可。当然了,一般不用,一般一类后处理器只有一个即可。
重点强调!: 这些接口的调用顺序并不是一尘不变的,会随便Spring的版本变动而变动,大家要做的是万变不离其宗,知道能够通过这些接口在Bean初始化的时做一些属性上的操作 。调用顺序要根据具体的版本来自己测试。下面我会给大家来列一个例子:
public class Student implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean,ApplicationContextAware { private String name; public Student(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("BeanFactoryAware......"); } @Override public void setBeanName(String s) { System.out.println("BeanNameAware......"); } @Override public void destroy() throws Exception { System.out.println("DisposableBean......"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("InitializingBean......"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("ApplicationContextAware......"); } }
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public MyBeanFactoryPostProcessor() { super(); System.out.println("这是BeanFactoryPostProcessor实现类构造器!!"); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException { System.out.println("BeanFactoryPostProcessor调用postProcessBeanFactory方法"); BeanDefinition bd = arg0.getBeanDefinition("student"); MutablePropertyValues propertyValues = bd.getPropertyValues(); //配置文件中的信息在加载到Spring中后以BeanDefinition的形式存在.在这里又可以更改BeanDefinition,所以可以理解为更改配置文件里面的内容 // propertyValues.add("zdy","123"); } }
public class MyBeanPostProcessor implements BeanPostProcessor { public MyBeanPostProcessor() { super(); System.out.println("这是BeanPostProcessor实现类构造器!!"); } @Override public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException { System.out.println("BeanPostProcessor接口方法After对属性进行更改!"); return arg0; } @Override public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException { System.out.println("BeanPostProcessor接口方法Before对属性进行更改!"); return arg0; } }
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter { public MyInstantiationAwareBeanPostProcessor() { super(); System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!"); } // 接口方法、实例化Bean之前调用 @Override public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException { System.out.println("InstantiationAwareBeanPostProcessor调用Before方法"); return null; } // 接口方法、实例化Bean之后调用 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("InstantiationAwareBeanPostProcessor调用Ater方法"); return bean; } // 接口方法、设置某个属性时调用 @Override public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { System.out.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法"); return pvs; } }
然后我们的Main方法:
public class App { public static void main( String[] args ) { ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml"); Student stu = (Student) ac.getBean("student"); stu.setName("wangwu"); } }
Spring文件最简单:( 注意要把我们自己定义的处理器全部加到容器里去 )
<?xml version="1.0" encoding="UTF-8"?> <beans <bean id="student" class="com.zdy.Student"> <constructor-arg value="zhangsan"/> </bean> <bean id="myBeanFactoryPostProcessor" class="com.zdy.MyBeanFactoryPostProcessor"></bean> <bean id="myInstantiationAwareBeanPostProcessor" class="com.zdy.MyInstantiationAwareBeanPostProcessor"></bean> <bean id="myBeanPostProcessor" class="com.zdy.MyBeanPostProcessor"></bean> </beans>
然后run一下子,看结果:
输出为: 这是BeanFactoryPostProcessor实现类构造器!! BeanFactoryPostProcessor调用postProcessBeanFactory方法 这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!! 这是BeanPostProcessor实现类构造器!! InstantiationAwareBeanPostProcessor调用Before方法 InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法 BeanNameAware...... BeanFactoryAware...... ApplicationContextAware...... BeanPostProcessor接口方法Before对属性进行更改! InitializingBean...... InstantiationAwareBeanPostProcessor调用Ater方法 BeanPostProcessor接口方法After对属性进行更改!
好了,其实大致流程就说完了,我大致针对Bean的生命周期说一下: Spring为了尽可能的把自己内部的东西机制暴露出来给用户使用,所以在Bean创建的过程中加了很多机制,通过所谓的"处理器"Processor暴露出来,然后处理器都有自己的顺序,我们需要做的就是定义好处理器的逻辑,然后注册到Sprinhg容器中,Spring就会调用了。其次,还有一种方式,就是让我们的Bean实现一些接口(类似于ApplicationContextAware),通过这种方式,在Bean初始化的某个步骤调用接口定义好的方法来传入一些信息进来,像ApplicationContextAware就把ApplicationContext给传给我们了。
然后我给大家说几个实用点的知识点,大家记着,用到时回来翻一翻就可以了:
好了,Bean的生命周期算上和大家分享完了,其实没什么东西,大家知道有这么回事,能用到"后处理器"搞事的时候回来大致看下顺序即可。其次就是一些Bean实现的接口,最常用的就是(ApplicationContextAware和InitializingBean)了。还有就是BeanPostProcessor,因为这个接口的方法里会把Bean实体以Object传进去。所以可以进行一些属性上的操作。其实说实在的,程序员用的比较少。框架内部用的多。OK,这篇讲的其实比较糙,主要是因为没什么东西可讲, Over,Have a good day !
感觉这期讲的不好,给大家一个传送门吧。感觉讲的比我还糙的一篇,大家结合着参考下 (^_^):