Spring IoC全注解开发-生命周期

上面我们只是关心如何正确的将bean装配到IoC容器中,而没有关心IoC容器如何装配和销毁Bean的过程。有时候我们也需要自定义初始化或者销毁Bean的过程,以满足一些Bean特殊初始化和销毁的要求。例如,上面的数据源,我们希望在其关闭的时候调用其close方法,以释放数据库的链接资源,这是在项目过程中很常见的要求。为了解决这些问题,我们有必要了解Spring IoC初始化和销毁Bean的过程,这就是Bean的生命周期的过程,他大致分为Bean定义,Bean的初始化, Bean的生存期,和Bean的销毁4个部分。其中Bean定义过程大致如下。

  • Spring通过我们的配置,如@ComponentScan定义的扫描路径去找带有@Component的类,这个过程就是一个资源定位的过程。
  • 一旦找到资源,那么他就开始解析,并且将定义的信息保存起来。注意此时此时还没有开始初始化Bean也就没有Bean实例,他有的仅仅是Bean的定义。
  • 然后就会将Bean定义发布到Spring IoC容器中。此时,IoC容器也只有Bean的定义,还是没有Bean的实例生成。
    完成这三步,只是将一个资源定位并将Bean的定义发布到IoC容器的过程。还没有Bean的实例生成,更没有完成依赖注入。在默认情况下,Spring会继续去完成Bean的实例化和依赖注入,这样在IoC容器中就可以得到一个依赖注入完成的Bean,但是,有些Bean会收到变化因素的影响,这时候,我们倒是希望在取出bean的时候完成初始化和依赖注入。换句话说,就是让那些Bean只是将定义发布到IoC容器而不是做实例化和依赖注入,当我们取出的时候才进行初始化和依赖注入等操作。
    下面我们先来了解一下Spring Bean的初始化流程
    在这里插入图片描述
    ComponentScan还有一个配置项lazyinit,只可以配置Boolean的值,且默认值为false,也就是默认不进行延迟初始化,因此在默认的情况下Spring会对bean进行实例化和依赖注入对应的属性值。
    为了进行测试,先改造BussinessPerson

/**
 * 人的实现类
 */
@Component
public class BussinessPersion implements Person {

   private Animal animal = null;

    @Override
    public void servie() {
        this.animal.use();

    }

    @Override
    @Autowired @Qualifier("cat")
    public void setAnimanl(Animal animanl) {
        System.out.println("延迟依赖注入");
        this.animal=animanl;
    }
}

然后我们在没有配置lazyInit的情况下进行断点测试

20:09:00.998 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bussinessPersion'
20:09:01.021 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'cat'
延迟依赖注入
20:09:01.022 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory 

在断点处我们并没有获得bean实例,而日志就已经打出了,可见他是在Spring IoC容器初始化时就执行了实例化和依赖注入。为了改变这个情况,我们在配置类Appconfig的@ComponentScan中加入lazyInit配置,如下代码:

@ComponentScan(value = "cn.hctech2006.boot.bootall.*",excludeFilters = {@ComponentScan.Filter(classes = {Service.class})},
        lazyInit = true)

然后进行测试,就会发现延迟依赖注入不会出现在日志中,只有运行到断点才会出现日志。
如果仅仅是实例化和依赖注入还是比较简单的,还不能完成进行自定义的要求。为了完成依赖注入的功能,Spring在完成依赖注入之后,还提供了一系列的接口和配置来完成Bean初始化的过程,让我们学习这个过程。Spring在完成依赖注入后,还会进行如下流程完成他的生命周期。
在这里插入图片描述
图中描述的是整个IoC容器初始化Bean的流程,作为开发者,需要注意这些流程。除此之外,还需要注意一下两点。

  • 这些方法和接口是针对什么而言,如图,在没有注释的情况下的流程节点都是针对单个Bean而言的,但是BeanPostProcessor是针对所有Bean而言的,这是我们需要注意的地方。
  • 只有实现了ApplicationContext接口的容器,才会在生命周期调用ApplicationContextAware所定义的setApplicationContext方法。
    为了测试生命周期,先来改造BussinessPerson
/**
 * 人的实现类
 * 加入生命接口和自定义
 */
@Component
public class BussinessPersion implements Person , BeanNameAware,
        BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean
{

   private Animal animal = null;

    @Override
    public void servie() {
        this.animal.use();

    }

    @Override
    @Autowired @Qualifier("cat")
    public void setAnimanl(Animal animanl) {
        System.out.println("延迟依赖注入");
        this.animal=animanl;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("["+this.getClass().getSimpleName()+"]调用BeanFactoryAware的setBeanFactory");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("["+this.getClass().getSimpleName()+"]调用BeanNameAware的setBeanName");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("["+this.getClass().getSimpleName()+"]调用DisposableBean的destory方法");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("["+this.getClass().getSimpleName()+"]调用InitializingBean的afterPropertiesSet");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("["+this.getClass().getSimpleName()+"]调用ApplicationContextAware的setApplicationCpntext");
    }
    @PostConstruct
    public void init(){
        System.out.println("["+this.getClass().getSimpleName()+"]调用PostContructor定义的自定义初始化方法");
    }
    @PreDestroy
    public void destory1(){
        System.out.println("["+this.getClass().getSimpleName()+"]调用PrePost定义的自定义销毁方法");
    }

}

这样这个Bean就实现了生命周期中单个Bean可以实现的所有接口,并且通过注解@PostConstruct定义了初始化方法,通过注解@PreDestory定义了销毁方法。为了测试Bean的后置处理器,这里创建一个类BeanPostProcessExample

package cn.hctech2006.boot.bootall.life;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * 后置Bean初始化器
 */
public class BeanPostProcessorExample implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor调用"+
                "postProcessorBeforeInitialization方法,参数["+
                bean.getClass().getSimpleName()+"]["+beanName+"]");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor调用"+
                "postProcessorAfterInitialization方法,参数["+
                bean.getClass().getSimpleName()+"]["+beanName+"]");
        return bean;
    }
}

注意,这个后置处理器将对所有的Bean有效,然后我们用一下代码进行测试

20:57:44.728 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
20:57:44.771 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/home/lidengyin/Downloads/code/boot-all/target/classes/cn/hctech2006/boot/bootall/bean/BussinessPersion.class]
20:57:44.771 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/home/lidengyin/Downloads/code/boot-all/target/classes/cn/hctech2006/boot/bootall/bean/Cat.class]
20:57:44.771 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/home/lidengyin/Downloads/code/boot-all/target/classes/cn/hctech2006/boot/bootall/bean/Dog.class]
20:57:44.771 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/home/lidengyin/Downloads/code/boot-all/target/classes/cn/hctech2006/boot/bootall/bean/User.class]
20:57:44.776 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/home/lidengyin/Downloads/code/boot-all/target/classes/cn/hctech2006/boot/bootall/controller/ControllerTest.class]
20:57:44.776 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/home/lidengyin/Downloads/code/boot-all/target/classes/cn/hctech2006/boot/bootall/life/BeanPostProcessorExample.class]
20:57:44.830 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
20:57:44.831 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
20:57:44.832 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
20:57:44.833 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
20:57:44.835 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanPostProcessorExample'
20:57:44.841 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'appConfig'
BeanPostProcessor调用postProcessorBeforeInitialization方法,参数[AppConfig$$EnhancerBySpringCGLIB$$f9c28b92][appConfig]
BeanPostProcessor调用postProcessorAfterInitialization方法,参数[AppConfig$$EnhancerBySpringCGLIB$$f9c28b92][appConfig]
20:57:44.842 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bussinessPersion'
20:57:44.863 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'cat'
BeanPostProcessor调用postProcessorBeforeInitialization方法,参数[Cat][cat]
BeanPostProcessor调用postProcessorAfterInitialization方法,参数[Cat][cat]
延迟依赖注入
[BussinessPersion]调用BeanFactoryAware的setBeanName
[BussinessPersion]调用BeanNameAware的setBeanFactory
[BussinessPersion]调用ApplicationContextAware的setApplicationCpntext
BeanPostProcessor调用postProcessorBeforeInitialization方法,参数[BussinessPersion][bussinessPersion]
[BussinessPersion]调用PostContructor定义的自定义初始化方法
[BussinessPersion]调用InitializingBean的afterPropertiesSet
BeanPostProcessor调用postProcessorAfterInitialization方法,参数[BussinessPersion][bussinessPersion]
20:57:44.864 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'dog'
BeanPostProcessor调用postProcessorBeforeInitialization方法,参数[Dog][dog]
BeanPostProcessor调用postProcessorAfterInitialization方法,参数[Dog][dog]
20:57:44.865 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'
BeanPostProcessor调用postProcessorBeforeInitialization方法,参数[User][user]
BeanPostProcessor调用postProcessorAfterInitialization方法,参数[User][user]
20:57:44.871 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'controllerTest'
BeanPostProcessor调用postProcessorBeforeInitialization方法,参数[ControllerTest][controllerTest]
BeanPostProcessor调用postProcessorAfterInitialization方法,参数[ControllerTest][controllerTest]
20:57:44.873 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'dataSource'
BeanPostProcessor调用postProcessorBeforeInitialization方法,参数[BasicDataSource][dataSource]
BeanPostProcessor调用postProcessorAfterInitialization方法,参数[BasicDataSource][dataSource]
20:57:44.901 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@2e5c649, started on Thu Apr 09 20:57:44 CST 2020
[BussinessPersion]调用PrePost定义的自定义销毁方法
[BussinessPersion]调用DisposableBean的setBeanFactory

Process finished with exit code 0

从日志可以看出,对于Bean后置处理器(BeanPostProcess)而言,他对所有的Bean都起作用,而其他接口则是对单个Bean起作用。我们还可以注意到BussinessPerson执行的流程是上图所画的流程。有时候Bean的定义可能使用第三方的类,此时可以使用注解@Bean来自定义初始化和销毁工作,如下所示:

@Bean(initMethod="init", destoryMethod="destory")
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值