玖叶教程网

前端编程开发入门

SpringBean生命周期管理系列之三:Spring创建对象的流程框架

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、一定要自己去跟代码,你想获得比单纯看博客文章多得多的知识,和更深的理解。同时也要去看博客,建立一个框架,然后跟源码,不停的调整框架,形成自己的独有的认知框架。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言