springbean生命周期

风景

前言

最近买了几本书,看了其中讲springboot的一本书,看到了讲spring bean的生命周期这一节,书上只是提了个大概,感觉不是自己想要的结果,还是自己动手吧;虽然写得不好,但是记一记还是对自己有好处的;

正文

在网上找了几张图,感觉有一张比较清楚:

avatar 接下来说一下几种方式吧,该项目使用springboot构建的;以下代码均在改项目中完成

1. 自定义初始化方法和销毁方法

新建一个bean类,注意该bean类上并没有使用注解

1
2
3
4
5
6
7
8
9
10
11

public class CustomBean {
    private final static Logger logger = LoggerFactory.getLogger(CustomBean.class);
    public void init(){
        logger.info("CustomBean-init");
    }
    public void destroy(){
        logger.info("CustomBean-destroy");
    }
}

自定义bean的初始化和销毁方法需要在配置文件中添加以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13

@Configuration
public class LifeCycleConfig {
    /**
     * 自定义bean的initMethod和destroyMethod
     * @return
     */
    @Bean(initMethod = "init",destroyMethod = "destroy")
    CustomBean customBean(){
        return new CustomBean();
    }
}

2. 使用注解的方式

使用@PostConstruct@PreDestroy两个注解,其中 @PostConstruct是在构方函数执行完之后指向性,@PreDestroy是在bean销毁前执行;

该bean类上使用了Component注解,当然,你还可以使用另外的那三个注解中的某一个;

1
2
3
4
5
6
7
8
9
10
11
12
13
14

@Component
public class AnnotationBean {
    private static final Logger logger= LoggerFactory.getLogger(AnnotationBean.class);
    @PostConstruct
    public void init(){
       logger.info("AnnotationBean-init");
    }
    @PreDestroy
    public void destroy(){
        logger.info("AnnotationBean-destroy");
    }
}

3.InitializingBean, DisposableBean

还可以继承InitializingBean, DisposableBean 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14

@Component
public class LifeCycleBean implements InitializingBean,DisposableBean {
    private static final Logger logger= LoggerFactory.getLogger(LifeCycleBean.class);
    @Override
    public void destroy() throws Exception {
        logger.info("LifeCycleBean-destroy");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        logger.info("LifeCycleBean-afterPropertiesSet");
    }
}

4.实现*Aware接口

在上边的图中可看见,有三个在最前面的三个Aware接口类,这些接口的功能就不用去说了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

@Component
public class LifeCycleBeanAware implements BeanNameAware,BeanFactoryAware,ApplicationContextAware {
    private static final Logger logger= LoggerFactory.getLogger(LifeCycleBeanAware.class);
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        logger.info("bean工厂");
    }
    @Override
    public void setBeanName(String s) {
        logger.info("bean的默认的名字:"+s);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        logger.info("bean上下文");
    }
}

5.BeanPostProcessor 增强处理器

这个类不是接口类,这个类中有两个方法postProcessBeforeInitializationpostProcessAfterInitialization

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

@Component
public class LifeCycleProcessor implements BeanPostProcessor {
    private static final Logger logger= LoggerFactory.getLogger(LifeCycleProcessor.class);
    private static final String DEFAULT_BEAN_NAME="annotationBean";
    /**
     *在bean初始化之前执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(DEFAULT_BEAN_NAME.equals(beanName)){
            logger.info("bean初始化之前执行:"+beanName);
        }
        return bean;
    }
    /**
     *bean初始化之后执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(DEFAULT_BEAN_NAME.equals(beanName)){
            logger.info("bean初始化之后执行:"+beanName);
        }
        return bean;
    }
}

启动后的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

2018-09-08 16:25:55.238  INFO 2584 --- [           main] com.gyc.bean.LifeCycleProcessor          : bean初始化之前执行:annotationBean
2018-09-08 16:25:55.238  INFO 2584 --- [           main] com.gyc.bean.AnnotationBean              : AnnotationBean-init
2018-09-08 16:25:55.238  INFO 2584 --- [           main] com.gyc.bean.LifeCycleProcessor          : bean初始化之后执行:annotationBean
2018-09-08 16:25:55.241  INFO 2584 --- [           main] com.gyc.bean.LifeCycleBean               : LifeCycleBean-afterPropertiesSet
2018-09-08 16:25:55.246  INFO 2584 --- [           main] com.gyc.bean.LifeCycleBeanAware          : bean的默认的名字:lifeCycleBeanAware
2018-09-08 16:25:55.246  INFO 2584 --- [           main] com.gyc.bean.LifeCycleBeanAware          : bean工厂
2018-09-08 16:25:55.246  INFO 2584 --- [           main] com.gyc.bean.LifeCycleBeanAware          : bean上下文
2018-09-08 16:25:55.279  INFO 2584 --- [           main] com.gyc.bean.CustomBean                  : CustomBean-init
2018-09-08 16:25:55.506  INFO 2584 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-09-08 16:25:55.539  INFO 2584 --- [           main] com.gyc.GycApplication                   : Started GycApplication in 1.922 seconds (JVM running for 3.01)
2018-09-08 16:25:55.544  INFO 2584 --- [       Thread-6] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@7b227d8d: startup date [Sat Sep 08 16:25:54 CST 2018]; root of context hierarchy
2018-09-08 16:25:55.548  INFO 2584 --- [       Thread-6] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
2018-09-08 16:25:55.549  INFO 2584 --- [       Thread-6] com.gyc.bean.CustomBean                  : CustomBean-destroy
2018-09-08 16:25:55.549  INFO 2584 --- [       Thread-6] com.gyc.bean.LifeCycleBean               : LifeCycleBean-destroy
2018-09-08 16:25:55.549  INFO 2584 --- [       Thread-6] com.gyc.bean.AnnotationBean              : AnnotationBean-destroy

示例代码-github

参考链接1:Spring中Bean的生命周期是怎样的?

参考链接2:Spring Bean 生命周期

总结

梳理了bean的生命周期,大概明白了spring对bean的一个处理流程;

对最上边的图进行详细描述:

  1. spring对bean进行实例化
  2. spring 将值和bean的引用注入到bean对应的属性当中;
  3. 如果bean实现了BeanNameAware接口,spring将bean的ID传递给setBeanName方法
  4. 如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory容器实例传入
  5. 如果bean实现了ApplicationContextAware接口,spring容器将调用setApplicationContext方法,将bean所在的应用上下文的引用传入进来
  6. 如果bean实现的BeanPostProcessor接口,spring将调用他们的postProcessBeforeInitialization方法;
  7. 如果bean实现了InitializeingBean接口,spring将调用他们的afterPropertiesSet方法。类似的,如果bean使用了init-method声明了初始化方法,该方法也会被调用;
  8. 如果bean实现的BeanPostProcessor接口,spring将调用他们的postProcessAfterInitialization方法
  9. bean被应用程序调用,直到该应用上下文被销毁;
  10. 如果bean实现了DisposableBean接口,spring将调用他的destroy方法。如果bean使用destroy-method声明销毁方法,该方法也会被调用
坚持原创技术分享,您的支持将鼓励我继续创作!