Spring对于Java开发者来说应该是再熟悉不过的一样东西了,这两天我把Spring的源码从官网下载下来并且进行编译,方便后面自己写一些测试用例(尽管被网速gank了很久),并且结合了网上的一些文章去理解Spring IOC方面的知识和运作过程,我也跟着一些文章敲了测试用例,通过控制台的输出去记忆bean的生命周期过程,毕竟之前一直靠背去记忆实在是太容易忘记了。当然这篇文章也不会讲的很详细,这篇文章是在我看了一天的文章和敲完用例趁着记忆还深刻来通过记录博客来加深记忆的,下面就开始吧。
Bean生命周期
这里首先贴出bean的一张生命周期图(图源来自JavaGuide)
其大致的流程其实也可以理解成下面这样,我相信等后面自己敲用例后,读者会对这一过程更加的记忆深刻了:
在开始初始化容器后,容器就会去配置文件
中读取关于bean的定义
,如果在配置bean时有赋予属性值,是可以读到这个值的。读取到定义后就会生成关于这个bean的实例。有实例之后就会对这个实例的属性进行设置set()。设置完属性后,如果检查到这个bean有实现比如BeanNameAware
、BeanFactoryAware
等这些诸如*Aware
的接口,那么就会调用它们对应的setBeanName(String beanName)
、setBeanFactory(BeanFactory factory)
等setXXX()
方法。在做完前面这些bean的实例化和属性设置的操作后就要开始进行初始化,BeanPostProcessor
这一处理器有postProcessBeforeInitialization()
和postProcessAfterInitialization()
两个方法,前者是在bean初始化前执行,后者就是在bean初始化完成后执行,也就是上图的前置和后置处理,可以自行去定义里面的行为,不过要注意因为这两个方法的返回值是作为一个新的bean实例,所以通常返回值都是传入进来的bean对象而不是null。在这初始化的过程中会检查这个bean有没有实现InitializingBean
接口,如果有的话则会去调用该接口的afterPropertiesSet()
方法,然后再检查配置文件的bean标签中有没有init-method
这一属性,有的话就会去调用配置文件里init-method
指定的初始化方法,初始化完成后就会执行上面所说得postProcessAfterInitialization
方法了。这样一个简单的容器初始化就这样完成了,然后就可以在容器中获取它。当我们要销毁容器时,会检查这个bean有没有实现DisposableBean
这个接口,如果有实现则会调用这个方法的destroy()
方法,然后再检查配置文件的bean标签有没有destroy-method
这一属性,有的话就会去调用配置文件里destroy-method
指定的销毁后的回调方法。至此一个简单的bean声明周期就这么结束了。
测试实现
实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| package com.demo.pojo;
import org.springframework.beans.BeansException; import org.springframework.beans.factory.*;
public class Person implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
private String name; private int age;
private BeanFactory beanFactory; private String beanName;
public Person(){ System.out.println("[构造器]调用Person的构造器实例化一个Person对象"); }
public String getName() { return name; }
public void setName(String name) { System.out.println("注入属性name,值为"+name); this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { System.out.println("注入属性age,值为"+age); this.age = age; }
@Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }
@Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("[BeanFactoryAware接口]调用BeanFactoryAware.setBeanFactory()方法"); this.beanFactory = beanFactory; }
@Override public void setBeanName(String name) { System.out.println("[BeanNameAware接口]调用BeanNameAware.setBeanName()方法"); this.beanName = name; }
@Override public void afterPropertiesSet() throws Exception { System.out.println("属性设置完后[InitializingBean接口]调用InitializingBean.afterPropertiesSet()方法"); }
@Override public void destroy() throws Exception { System.out.println("要销毁bean时[DisposableBean接口]调用DisposableBean.destroy()"); }
public void myInit(){ System.out.println("[init-method]调用<bean>的init-method属性指定的初始化方法"); }
public void myDestroy(){ System.out.println("[destroy-method]调用<bean>的destroy-method属性指定的初始化方法"); } }
|
Processor
BeanFactoryPostProcessor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package com.demo.processor;
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() { super(); System.out.println("BeanFactoryPostProcessor类构造方法"); System.out.println("---------"); }
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("[BeanFactoryPostProcessor接口]postProcessBeanFactory方法在加载完bean的定义后,在bean实例化前进行修改"); BeanDefinition bd = beanFactory.getBeanDefinition("person"); StringBuilder sb = new StringBuilder(); sb .append("beanName: person") .append(",beanClassName: ").append(bd.getBeanClassName()) .append(",factoryBeanName: ").append(bd.getFactoryBeanName()) .append(",factoryMethodName: ").append(bd.getFactoryMethodName()) .append(",scope: ").append(bd.getScope()) .append(",parent: ").append(bd.getParentName()) .append(",nameValues: ").append(bd.getPropertyValues().get("name")) .append(",ageValues: ").append(bd.getPropertyValues().get("age")); System.out.println("该定义bean的信息为:"); System.out.println(sb.toString()); System.out.println("---------"); bd.getPropertyValues().addPropertyValue("name","jason"); bd.getPropertyValues().addPropertyValue("age","21"); } }
|
BeanPostProcessor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package com.demo.processor;
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor { public MyBeanPostProcessor(){ super(); System.out.println("BeanPostProcessor类构造器"); System.out.println("----------"); }
@Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("[BeanPostProcessor接口]postProcessBeforeInitialization执行初始化前任务"); return bean; }
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("[BeanPostProcessor接口]postProcessAfterInitialization执行初始化完成后任务"); return bean; } }
|
InstantiationAwareBeanPostProcessor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package com.demo.processor;
import org.springframework.beans.BeansException; import org.springframework.beans.PropertyValues; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
public MyInstantiationAwareBeanPostProcessor() { super(); System.out.println("InstantiationAwareBeanPostProcessor类构造器"); System.out.println("-----------"); }
@Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { System.out.println("[InstantiationAwareBeanPostProcessor接口]postProcessBeforeInstantiation在bean实例化前执行,此时没有bean对象"); return null; }
@Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { System.out.println("[InstantiationAwareBeanPostProcessor接口]postProcessAfterInstantiation在bean实例化后执行,此时有bean对象"); return true; }
@Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { System.out.println("假装postProcessProperties执行修改"); System.out.println("---------"); return pvs; } }
|
配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="beanPostProcessor" class="com.demo.processor.MyBeanPostProcessor"></bean>
<bean id="instantiationAwareBeanPostProcessor" class="com.demo.processor.MyInstantiationAwareBeanPostProcessor"></bean>
<bean id="beanFactoryPostProcessor" class="com.demo.processor.MyBeanFactoryPostProcessor"></bean>
<bean id="person" class="com.demo.pojo.Person" init-method="myInit" destroy-method="myDestroy" scope="singleton" p:name = "john" p:age = "22" /> </beans>
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.demo;
import com.demo.pojo.Person; import com.demo.service.TestHelloService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main { public static void main(String[] args) { System.out.println("----开始初始化容器----"); ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:spring-config.xml"); System.out.println("----初始化容器成功----"); System.out.println("获取bean"); Person person = ctx.getBean("person", Person.class); System.out.println(person); System.out.println("----开始关闭容器----"); ((ClassPathXmlApplicationContext)ctx).registerShutdownHook(); } }
|
结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| ----开始初始化容器---- BeanFactoryPostProcessor类构造方法 --------- [BeanFactoryPostProcessor接口]postProcessBeanFactory方法在加载完bean的定义后,在bean实例化前进行修改 该定义bean的信息为: beanName: person,beanClassName: com.demo.pojo.Person,factoryBeanName: null,factoryMethodName: null,scope: singleton,parent: null,nameValues: john,ageValues: 22 --------- BeanPostProcessor类构造器 ---------- InstantiationAwareBeanPostProcessor类构造器 ----------- [InstantiationAwareBeanPostProcessor接口]postProcessBeforeInstantiation在bean实例化前执行,此时没有bean对象 [构造器]调用Person的构造器实例化一个Person对象 [InstantiationAwareBeanPostProcessor接口]postProcessAfterInstantiation在bean实例化后执行,此时有bean对象 假装postProcessProperties执行修改 --------- 注入属性age,值为21 注入属性name,值为jason [BeanNameAware接口]调用BeanNameAware.setBeanName()方法 [BeanFactoryAware接口]调用BeanFactoryAware.setBeanFactory()方法 [BeanPostProcessor接口]postProcessBeforeInitialization执行初始化前任务 属性设置完后[InitializingBean接口]调用InitializingBean.afterPropertiesSet()方法 [init-method]调用<bean>的init-method属性指定的初始化方法 [BeanPostProcessor接口]postProcessAfterInitialization执行初始化完成后任务 ----初始化容器成功---- 获取bean Person{name='jason', age=21} ----开始关闭容器---- 要销毁bean时[DisposableBean接口]调用DisposableBean.destroy() [destroy-method]调用<bean>的destroy-method属性指定的初始化方法
|
通过打印语句就能很直观地看到这个过程:容器初始化后先构造BeanFactoryPostProcessor,然后调用其postProcessBeanFactory方法,获取bean的定义。接着构造BeanPostProcessor和InstantiationAwareBeanPostProcessor。到这里都还是没有bean对象的,在实例化bean之前就会调用InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法,接着实例化bean,实例化之后调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation方法,这个方法返回值如果是true的话就会触发postProcessProperties的调用。bean实例化好后,就对其属性进行注入,对于实现的Aware接口调用对应的set方法。这样bean的实例化和属性设置就完成了,接下来就是要初始化,在初始化前,BeanPostProcessor会执行postProcessBeforeInitialization这一方法,然后就是初始化的操作,检查到实现了InitializingBean接口和有配置init-method,执行InitializingBean.afterPropertiesSet()方法和<bean>的init-method属性指定的初始化方法,初始化完成后BeanPostProcessor就会执行postProcessAfterInitialization这一方法,容器的初始化也就完成了,接着的就是模拟一下获取bean的操作。关闭容器时,检查到实现了DisposableBean接口和配置了destroy-method,执行DisposableBean.destroy()方法和<bean>的destroy-method属性指定的销毁后的回调方法。
这便是一个简单的bean生命周期过程了。
参考