Spring源码分析:Bean生命周期源码分析

/ Spring源码分析 / 1 条评论 / 94人围观

所谓Bean的生命周期就是从Bean的创建 ---> Bean的初始化 ---> Bean销毁的过程。

Spring为我们提供了三种方式来指定Bean的生命周期
1. 注解方式
2. InitializingBean和DisposableBean接口方式
3. JSR330方式
单例情况下:
    在单例情况下,Bean的构造方法和init方法会先后执行,销毁方法是在容器关闭之前才会执行。
多例情况下:
    在多例情况下,Bean的构造方法和init方法只有在从容器中获取Bean的时候才会执行,
    而销毁方法Spring并不会干预,只能手动调用。

注解方式

实体类:

/**
 * @author 70KG
 * @Title: Bike
 * @Description:
 * @From www.nmyswls.com
 */
public class Bike {

    public Bike() {
        System.out.println("Bike构造方法执行...");
    }

    public void initMethod() {
        System.out.println("Bike...initMethod初始化方法执行...");
    }

    public void destroyMethod() {
        System.out.println("Bike...destroyMethod销毁方法执行...");
    }

}

配置类:

/**
 * @author 70KG
 * @Description:
 * @From www.nmyswls.com
 */
@Configuration
public class BikeConfig {

    // @Scope("prototype") // 对于多实例来说仅当使用到bean对象的时候才会有对象的生成
    // 指定类的初始化方法和销毁方法。
    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public Bike bike() {
        return new Bike();
    }

}

测试类:

/**
 * @author 70KG
 * @Description:
 * @From www.nmyswls.com
 */
public class Test01 {

    @Test
    public void test() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(BikeConfig.class);
        //ac.close();
    }

}

接口方式

实体Bean:

/**
 * description
 *
 * @author 70KG
 * @date 2019/1/17
 */
public class Car implements InitializingBean, DisposableBean {

    public Car() {
        System.out.println("Car...Constructor...");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("Car...destroy...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Car...init...");
    }
}

配置类:

/**
 * description
 *
 * @author 70KG
 */
@Configuration
public class CarConfig {

    @Bean
    public Car car() {
        return new Car();
    }

}

测试类:

/**
 * @author 70KG
 * @Description:
 * @From www.nmyswls.com
 */
public class Test01 {

    @Test
    public void test() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(CarConfig.class);
        ac.close();
    }

}

JSR330方式

实体Bean:

/**
 * description
 *
 * @author 70KG
 * @date 2019/1/17
 */
public class RainBow {

    public RainBow() {
        System.out.println("RainBow...Constructor");
    }

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

    @PreDestroy
    public void destroy() {
        System.out.println("RainBow...destroy...");
    }

}

配置类:

/**
 * description
 *
 * @author 70KG
 * @date 2019/1/17
 */
@Configuration
public class RainBowConfig {

    @Bean
    public RainBow rainBow() {
        return new RainBow();
    }

}

测试类:

/**
 * @author 70KG
 * @Description:
 * @From www.nmyswls.com
 */
public class Test01 {

    @Test
    public void test() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(RainBowConfig.class);
        ac.close();
    }

}

初始化方法源码分析

基于Spring5.0

AnnotationConfigApplicationContext构造方法中的refresh();
-> AbstractApplicationContext550行finishBeanFactoryInitialization(beanFactory);完成剩余Bean的初始化工作
-> AbstractApplicationContext869行beanFactory.preInstantiateSingletons();
-> DefaultListableBeanFactory760行getBean(beanName);
-> AbstractBeanFactory317行createBean(beanName, mbd, args);
-> AbstractAutowireCapableBeanFactory503行doCreateBean(beanName, mbdToUse, args);
-> AbstractAutowireCapableBeanFactory581行initializeBean(beanName, exposedObject, mbd);准备执行初始化方法
-> AbstractAutowireCapableBeanFactory1704行invokeInitMethods(beanName, wrappedBean, mbd);真正执行初始化方法
说一下AbstractAutowireCapableBeanFactory类的invokeInitMethods方法
首先判断此类是否实现的是InitializingBean接口,相当于我们实现的InitializingBean一样,如果是,
就利用反射调取接口方法执行Bean的初始化工作,
如果不是,看一下是否有用户自定义的初始化方法,例如:String initMethodName = mbd.getInitMethodName();
StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) 
&& !mbd.isExternallyManagedInitMethod(initMethodName)
1. initMethodName有长度
2. 用户不是以afterPropertiesSet命名并且没有实现InitializingBean接口
3. 自定义的名字不在这个Set集合中包括
那么就执行用户自定义的方法1776行invokeCustomInitMethod(beanName, bean, mbd);也是利用了反射。
销毁的方法类似。
  1. 我去二群啊

    回复