Spring Bean与Java Bean相比较,就是由Spring IOC容器负责实例化、组装、管理,而Java Bean需要用户自己创建、管理和使用,其基本流程是创建对象(new一个对象),使用对象,使用完成之后JVM自动进行垃圾回收。Spring Bean在整个生命周期,提供了很多的切入点,用户可以根据实际的情况进行干预,在确定主线的前提下,最大化的提供灵活性。
在一边Spring跟源码,一边分析之后,画出了Spring Bean的生命周期如下图所示:
Spring Bean创建流程框架
根据上图,可以看出启动Java程序,首先启动JVM,然后找到main入口类,开始Spring Bean的生命周期。
第一,进行Spring容器的准备工作,创建容器工厂,创建Spring容器,创建BeanFactory;
第二,扫描XML和注解,把Bean包装成BeanDefinition放在beanDefinitionMap中;
第三,调用BeanFactoryPostProcessor的后置处理器方法;
第四,进行对象实例化之前,可以调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation方法;
第五,实例化,根据构造函数创建对象;
第六,实例化之后,调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation方法;
第七,实例化之后,调用InstantiationAwareBeanPostProcessor.postProcessProperties方法;
第八,设置对象的属性,通过Spring的依赖注入实现;
第九,如果实现了Aware接口,则引入相对应的对象作为类的变量;
第十,对象初始化之前,调用Bean后置处理器postProcessBeforeInitialization方法;
第十一,对象初始化,即调用InitializingBean.afterPropertiesSet方法或调用init-method方法;
第十三,对象初始化之后,调用Bean后置处理器postProcessAfterInitialization方法;
第十四,如果生成的对象为singleton类型,则存放入Spring容器,供程序使用,使用完成之后,会调用DisposableBean.destroy方法,调用destroy-method方法;如果生成的对象为prototype类型,则用户自己管理,重新向Spring容器获取对象时,会重新创建一个新对象。
职责划分
弄清楚Spring Bean的生命周期,尤其是可以干预点,特别的重要,因为Spring的重要特性都是通过这些切入点完成的,比如AOP、IOC等。其实从整个过程来看,我们简单从层次的角度做一下划分。
第一层,是JVM层,Java程序要运行必须要先启动JVM,JVM的启动流程和原理这里就不展开了;
第二层,是Spring工厂层,这一层主要通过BeanFactoryProcessor,及其子接口来实现;
第三层,是Spring容器类,是Spring的重点,主要是InstantiationAwareBeanPostProcessor、BeanPostProcessor等后置处理器,这些处理器对于所有Spring容器的Bean都起作用,这一点特别重要。
第四层,类自身的方法,比如构造函数、getter和setter函数、实现的InitializingBean, BeanNameAware, DisposableBean,ApplicationContextAware等接口。
代码实现
Listen类:
@Component
public class Listen implements InitializingBean, BeanNameAware, DisposableBean,ApplicationContextAware {
private String who;
private String how;
private String when;
public Listen()
{
}
public Listen(String who,String how,String when){
this.who = who;
this.how = how ;
this.when = when;
System.out.println("======Listen 调用构造函数");
}
public String getWho() {
return who;
}
@Value("${english.listen.who}")
public void setWho(String who) {
this.who = who;
System.out.println("======Listen 调用属性注入{who}");
}
public String getHow() {
return how;
}
@Value("${english.listen.how}")
public void setHow(String how) {
this.how = how;
System.out.println("======Listen 调用属性注入{how}");
}
public String getWhen() {
return when;
}
@Value("${english.listen.when}")
public void setWhen(String when) {
this.when = when;
System.out.println("======Listen 调用属性注入{when}");
}
public void myInit(){
System.out.println("======Listen 调用init-method方法");
}
public void myDestroy(){
System.out.println("======Listen 调用destroy-method方法");
}
@Override
public void setBeanName(String name) {
System.out.println("======Listen 调用BeanNameAware.setBeanName方法");
}
@Override
public void destroy() throws Exception {
System.out.println("======Listen 调用DisposableBean.destroy方法");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("======Listen 调用InitializingBean.afterPropertiesSet方法");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("======Listen 调用ApplicationContextAware.ApplicationContextAware方法");
}
}
TestBeanFactoryPostProcessor类:
@Component
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("======TestBeanFactoryPostProcessor 调用BeanFactoryPostProcessor.postProcessBeanFactory方法");
}
}
TestBeanPostProcessor类:
@Component
public class TestBeanPostProcessor implements BeanPostProcessor, InstantiationAwareBeanPostProcessor {
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("======TestBeanPostProcessor 调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation: beanName = "+beanName);
return null;
}
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("======TestBeanPostProcessor 调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation: beanName = "+beanName);
return true;
}
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
System.out.println("======TestBeanPostProcessor 调用InstantiationAwareBeanPostProcessor.postProcessProperties: beanName = "+beanName);
return null;
}
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("======TestBeanPostProcessor 调用BeanPostProcessor.postProcessBeforeInitialization方法: beanName = "+beanName);
return bean;
}
@Nullable
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("======TestBeanPostProcessor 调用BeanPostProcessor.postProcessAfterInitialization方法: beanName = "+beanName);
return bean;
}
}
MyEnglishMain入口函数:这里采用单独加载特定类的方式,以减少干扰信息。
public class MyEnglishMain {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("TestBean.xml");
Listen listen =(Listen) applicationContext.getBean("listen");
((AbstractApplicationContext)applicationContext) .close();
}
}
TestBean.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.cn.lx.study"></context:component-scan>
<bean id="listen" class="com.cn.lx.study.english.pojo.Listen" init-method="myInit" destroy-method="myDestroy">
<constructor-arg index="0" type="java.lang.String" value="dibin">
</constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="listening">
</constructor-arg>
<constructor-arg index="2" type="java.lang.String" value="2022">
</constructor-arg>
<property name="who" value="dd"></property>
<property name="how" value="listening-2022"></property>
<property name="when" value="2022-12"></property>
</bean>
</beans>
执行结果:这里删除了其他无关信息
特殊说明
1、如果一个类实现了InitializingBean, BeanNameAware, DisposableBean,ApplicationContextAware,也实现了BeanFactoryPostProcessor、BeanPostProcessor、InstantiationAwareBeanPostProcessor接口,Spring会首先构造实现BeanFactoryPostProcessor、BeanPostProcessor、InstantiationAwareBeanPostProcessor接口的类,导致BeanNameAware、InitializingBean在前执行。
2、一定要自己去跟代码,你想获得比单纯看博客文章多得多的知识,和更深的理解。同时也要去看博客,建立一个框架,然后跟源码,不停的调整框架,形成自己的独有的认知框架。