Bean生命周期

Spring需要使用的组件配置pom.xml

1.Bean声明周期概述

Bean的生命周期:指bean“创建-----初始化----销毁”的过程。
Bean的生命周期是由容器进行管理的。
我们可以自定义 Bean初始化和销毁方法: 容器在Bean进行到当前生命周期的时候, 来调用自定义的初始化和销毁方法

2.Bean初始化和销毁的三种方式

2.1 指定初始化和销毁方法

在配置类里通过@Bean(initMethod="init", destroyMethod="destroy")指定
需要注册的Bean:Bike.java

public class Bike {
    public Bike(){
        System.out.println("Bike constructor..............");
    }
    public void init(){
        System.out.println("Bike .....init.....");
    }
    public void destory(){
        System.out.println("Bike.....destory");
    }
}

配置类中指定Bike的init和destory方法

    //@Scope("prototype")
    @Bean(initMethod="init", destroyMethod="destory")
    public Bike bike(){
        return new Bike();
    }

测试类Ch7Test.java

public class Ch7Test {
    @Test
    public void test01() {
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Ch7MainConfigOfLifeCycle.class);

        System.out.println("IOC容器创建完成........");
        app.close();
    }
}

结果如下:

给容器中添加person.......
Bike constructor..............
Bike .....init.....
IOC容器创建完成........
Bike.....destory

2.2 让Bean实现 InitializingBean 和 DisposableBean接口

  • InitializingBean(定义初始化逻辑,可点进去看此类):afterPropertiesSet()方法:当beanFactory创建好对象,且把bean所有属性设置好之后,会调这个方法,相当于初始化方法
  • DisposableBean(定义销毁逻辑,可点进去看此类):destory()方法,当bean销毁时,会把单实例bean进行销毁

实现 InitializingBean 和 DisposableBean接口的Train.java

@Component
public class Train implements InitializingBean, DisposableBean {

    public Train(){
        System.out.println("Train......constructor............");
    }
    //当我们bean销毁时,调用此方法
    @Override
    public void destroy() throws Exception {
        System.out.println("Train......destory......");
        //logger.error
    }
    //当我们的bean属性赋值和初始化完成时调用
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Train.......afterPropertiesSet()...");
    }
}

配置类

@ComponentScan("com.wangzhen.ch7.bean")
@Configuration
public class Ch7MainConfigOfLifeCycle {
    @Bean("person")
    public Person person(){
        System.out.println("给容器中添加person.......");
        return new Person("person",20);
    }

    //@Scope("prototype")
    @Bean(initMethod="init", destroyMethod="destory")
    public Bike bike(){
        return new Bike();
    }
}

结果

Train......constructor............
Train.......afterPropertiesSet()...
IOC容器创建完成........
Train......destory......

2.3 使用JSR250规则定义的(java规范)两个注解来实现

  • @PostConstruct: 在Bean创建完成,且属于赋值完成后进行初始化,属于JDK规范的注解
  • @PreDestroy: 在bean将被移除之前进行通知, 在容器销毁之前进行清理工作

Jeep.java

@Component
public class Jeep {
    public Jeep(){
        System.out.println("Jeep.....constructor........");
    }
    @PostConstruct
    public void init(){
        System.out.println("Jeep.....@PostConstruct........");
    }

    @PreDestroy
    public void destory(){
        System.out.println("Jeep.....@PreDestroy......");
    }

}

结果:

Jeep.....constructor........
Jeep.....@PostConstruct........
IOC容器创建完成........
Jeep.....@PreDestroy...

3.后置处理器

负责在初始化方法前后作用。

BeanPostProcessor类[interface]: bean的后置处理器,在bean初始化之前调用进行拦截。
作用:在bean初始化前后进行一些处理工作:

  • 1)postProcessBeforeInitialization():在初始化之前进行后置处理工作(在init-method之前)
    什么时候调用:它任何初始化方法调用之前(比如在InitializingBean的afterPropertiesSet初始化之前,或自定义init-method调用之前使用)
  • 2) postProcessAfterInitialization():在初始化之后进行后置处理工作, 比如在InitializingBean的afterPropertiesSet()
//AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

实现后置处理器接口BeanPostProcessor的JamesBeanPostProcessor.java

@Component
public class JamesBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //返回一个的对象(传过来的对象)
        //在初始化方法调用之前进行后置处理工作,
        //什么时候调用它: init-method=init之前调用
        System.out.println("postProcessBeforeInitialization...."+beanName+"..."+bean);
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization...."+beanName+"..."+bean);
        return bean;
    }
}

结果:

Bike constructor..............
postProcessBeforeInitialization....bike...com.wangzhen.ch7.bean.Bike@1e81f160
Bike .....init.....
postProcessAfterInitialization....bike...com.wangzhen.ch7.bean.Bike@1e81f160
IOC容器创建完成........

4.BeanPostProcessor原理以及三个后置处理器的分析(对bean的增强)

BeanPostProcessor的作用:

  • bean的赋值
  • 注入其它组件
  • 生命周期注解功能(都是通过后置处理器来实现注解功能)
  • @Async等等

4.1 后置处理器的跟踪

AnnotationConfigApplicationContext-->refresh()-->
finishBeanFactoryInitialization(beanFactory)--->
beanFactory.preInstantiateSingletons()-->
760行getBean(beanName)--->
199行doGetBean(name, null, null, false)-->
317行createBean(beanName, mbd, args)-->
501行doCreateBean(beanName, mbdToUse, args)-->
541行createBeanInstance(beanName, mbd, args)(完成bean创建)-->
578行populateBean(beanName, mbd, instanceWrapper)(属性赋值)-->
579行initializeBean(beanName, exposedObject, mbd)(Bean初始化)->
1069行到1710行,后置处理器完成对init方法的前后处理.

最终得到如下如下
createBeanInstance(beanName, mbd, args)(完成bean创建)
populateBean(beanName, mbd, instanceWrapper); 给bean进行属性赋值
initializeBean() //初始化Bean方法内容如下,后置处理器对init方法的前后处理
{
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
invokeInitMethods(beanName, wrappedBean, mbd) //执行自定义初始化
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
}

4.2 ApplicationContextAwareProcessor实现分析

此类帮我们组建IOC容器,跟进ApplicationContextAwareProcessor我们发现,这个后置处理器其实就是判断我们的bean有没有实现ApplicationContextAware 接口,并处理相应的逻辑,其实所有的后置处理器原理均如此。
那么怎么组建呢? 只需要实现 ApplicationContextAware 接口。
实现 ApplicationContextAware 接口的Plane.java

@Component
public class Plane implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    public Plane() {
        System.out.println("Plane.....constructor........");
    }

    @PostConstruct
    public void init(){
        System.out.println("Plane.....@PostConstruct........");
    }

    @PreDestroy
    public void destory(){
        System.out.println("Plane.....@PreDestroy......");
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //将applicationContext传进来,可以拿到
        this.applicationContext = applicationContext;
    }
}

分析源码如下:

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }
//ApplicationContextAwareProcessor实现的postProcessBeforeInitialization
    @Override
    @Nullable
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;

        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged((PrivilegedAction) () -> {
                invokeAwareInterfaces(bean);
                return null;
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean);
        }

        return bean;
    }
 
 
  • step1.在创建Plane对象,还没初始化之前, 先判断是不是实现了ApplicationContextAware接口,
    如果是的话就调用invokeAwareInterfaces方法, 并给里面注入值;

  • step2.进入invokeAwareInterfaces()方法,判断是哪个aware, 如果是ApplicationContextAware, 就将当前的bean转成ApplicationContextAware类型, 调用setApplicationContext(), 把IOC容器注入到Plane里去;

  • step3.用debug调用; 测试用例打断点测试


    Bean生命周期_第1张图片
  • step4.也可看debug调用栈来分析;
    : debug可以打在ApplicationContextAwareProcessor处理器类的applyBeanPostProcessorsBeforeInitialization()方法里, 方便调试, 当bean为Plane类型时,F5跟进看, 最终在 InvokeAwareInterfaces()方法里返回我们的IOC容器applicationContext.

4.3 BeanValidationPostProcessor分析:数据校验

Bean生命周期_第2张图片

当对象创建完,给bean赋值后,在WEB用得特别多;把页面提交的值进行校验。


Bean生命周期_第3张图片

4.4 InitDestroyAnnotationBeanPostProcessor

Bean生命周期_第4张图片

此处理器用来处理@PostConstruct, @PreDestroy, 怎么知道这两注解是前后开始调用的呢, 就是 InitDestroyAnnotationBeanPostProcessor这个处理的。


Bean生命周期_第5张图片

以@PostConstruct为例, 为什么声明这个注解后就能找到初始化init方法呢?


Bean生命周期_第6张图片

Bean生命周期_第7张图片

参考

  • 1)享学课堂James老师笔记

你可能感兴趣的:(Bean生命周期)