06 sping注解开发-Bean的生命周期

1 Bean的生命周期

bean的声明周期:

  1. 创建
  2. 初始化
  3. 销毁

我们可以自定义初始化和销毁方法,容器在bean执行到当前生命周期的时候来调用自己定义的初始化和销毁逻辑
为了演示bean声明周期,将在创建一个新的包,用于测试演示。

1.1 创建

之前已经提过:
单实例:在容器启动的时候创建
多实例:在每次获取的时候创建

1.2 初始化

单实例:对象创建完,并赋值好,调用初始化方法
多实例:对象创建完,并赋值好,调用初始化方法

1.3 销毁

单实例:容器关闭的时候执行销毁逻辑
多实例:容器不会管理这个Bean,容器不会调用销毁方法,需要自己手动调用

2 @Bean注解中指定初始化和销毁方法

2.1 使用

  1. 定义一个Bean:LifeBean
@Slf4j
public class LifeBean {

    public LifeBean() {
        log.info("LifeBean constructor。。。");
    }
    public void init(){
        log.info("LifeBean init。。。");
    }
    public void destroy(){
        log.info("LifeBean destroy。。。");
    }

}
  1. 定义一个配置类,指定包扫描和配置刚刚的bean
@Configuration
// 只扫描这包,为了不让之前的会测试代码污染我们的测试效果
@ComponentScan("study.wyy.spring.anno.life")
public class MainLiftCycleConfig {

    @Bean(initMethod = "init",destroyMethod = "destroy")
    public LifeBean lifeBean(){
        return new LifeBean();
    }
}
  • initMethod: 指定bean初始化逻辑的方法
  • destroyMethod: 指定bean逻辑的销毁方法
  1. 测试
 /**
     * 测试单实例bean的声明周期
     */
    @Test
    public void test01(){
        // 创建ioc容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
        log.info("ioc容器创建完成。。。");
    }

日志结果:

[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean init。。。
[main] INFO lifetest.Test01 - ioc容器创建完成。。

可见在单实例在容器创建完成时,就完成单实例bean的创建和初始化
那何时销毁呢—>在容器关闭的时候:

 @Test
    public void test01(){
        // 创建ioc容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
        log.info("ioc容器创建完成。。。");
        applicationContext.close();
    }

日志结果:

[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean init。。。
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean destroy。。。

上面测试的是单实例bean的生命周期
下面测试多实例bean的声明周期,使用@Scope注解

@Configuration
@ComponentScan("study.wyy.spring.anno.life")
public class MainLiftCycleConfig {

    @Bean(initMethod = "init",destroyMethod = "destroy")
    @Scope("prototype")
    public LifeBean lifeBean(){
        return new LifeBean();
    }   
}
 /**
     * 测试多实例bean的声明周期
     */
    @Test
    public void test02(){
        // 创建ioc容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
        log.info("ioc容器创建完成。。。");
        LifeBean bean = applicationContext.getBean(LifeBean.class);
        applicationContext.close();
    }

日志结果:

[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean init。。。

发现多实例在每次获取的时候执行创建和初始化,但是容器关闭的时候不会执行销毁逻辑

3 InitializingBean , DisposableBean

3.1 介绍

public interface InitializingBean {
	/**
	 * Invoked by a BeanFactory after it has set all bean properties supplied
	 * (and satisfied BeanFactoryAware and ApplicationContextAware).
	 * <p>This method allows the bean instance to perform initialization only
	 * possible when all bean properties have been set and to throw an
	 * exception in the event of misconfiguration.
	 * @throws Exception in the event of misconfiguration (such
	 * as failure to set an essential property) or if initialization fails.
	 */
	 // bean的属性设置完成之后执行
	 void afterPropertiesSet() throws Exception;
}
public interface DisposableBean {

	/**
	 * Invoked by a BeanFactory on destruction of a singleton.
	 * @throws Exception in case of shutdown errors.
	 * Exceptions will get logged but not rethrown to allow
	 * other beans to release their resources too.
	 */
	 // 销毁的时候执行
	void destroy() throws Exception;

}

3.2 演示

  1. 定义一个Bean实现这两个接口
@Slf4j
public class LifeBean2 implements InitializingBean , DisposableBean {

    public LifeBean2() {
        log.info("LifeBean2 constructor。。。");
    }
    /**
     * 销毁的时候执行
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        log.info("LifeBean2 destroy。。。");
    }

    /**
     * bean的属性设置完成之后执行
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("LifeBean2 afterPropertiesSet。。。");
    }
}
  1. 配置这个bean
    为了不影响避免过多日志输出,先不注册之前演示的Bean
@Configuration
@ComponentScan("study.wyy.spring.anno.life")
public class MainLiftCycleConfig {

    /*@Bean(initMethod = "init",destroyMethod = "destroy")
    @Scope("prototype")
    public LifeBean lifeBean(){
        return new LifeBean();
    }*/
    @Bean
    public LifeBean2 lifeBean2(){
        return new LifeBean2();
    }
}
  1. 测试
  /**
     * 测试单实例bean的声明周期
     */
    @Test
    public void test01(){
        // 创建ioc容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
        log.info("ioc容器创建完成。。。");
        applicationContext.close();
    }

日志结果:

[main] INFO study.wyy.spring.anno.life.bean.LifeBean2 - LifeBean2 constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean2 - LifeBean2 afterPropertiesSet。。。
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean2 - LifeBean2 destroy。。。
  /**
     * 测试多实例bean的声明周期
     */
    @Test
    public void test03(){
        // 创建ioc容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
        log.info("ioc容器创建完成。。。");
        LifeBean2 bean = applicationContext.getBean(LifeBean2.class);
        applicationContext.close();
    }
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean2 - LifeBean2 constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean2 - LifeBean2 afterPropertiesSet。。。

4 JSR250

  • @PostConstruct: bean创建完成并属性赋值完成的时候执行
  • @PreDestroy: 容器销毁的对象的前通知
@Slf4j
public class LifeBean3  {

    public LifeBean3() {
        log.info("LifeBean3 constructor。。。");
    }
    /**
     * 容器销毁的对象的前通知
     * @throws Exception
     */
    @PreDestroy
    public void destroy() throws Exception {
        log.info("LifeBean2 destroy。。。");
    }

    /**
     * bean创建完成并属性赋值完成的时候执行
     * @throws Exception
     */
    @PostConstruct
    public void afterPropertiesSet() throws Exception {
        log.info("LifeBean2 afterPropertiesSet。。。");
    }
}
@Configuration
@ComponentScan("study.wyy.spring.anno.life")
public class MainLiftCycleConfig {
    @Bean
    public LifeBean3 lifeBean3(){
        return new LifeBean3();
    }
}
@Test
    public void test04(){
        // 创建ioc容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
        log.info("ioc容器创建完成。。。");
        LifeBean3 bean = applicationContext.getBean(LifeBean3.class);
        applicationContext.close();
    }
[main] INFO study.wyy.spring.anno.life.bean.LifeBean3 - LifeBean3 constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean3 - LifeBean2 afterPropertiesSet。。。
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean3 - LifeBean2 destroy。。。

5 三者比较

上述提供的3个初始化和销毁的方式,这三个之间的顺序又是如何呢

  1. 一个Bean通过上面三个方式进行初始化
@Slf4j
public class LifeBean4 implements InitializingBean , DisposableBean {

    public LifeBean4() {
        log.info("LifeBean4 constructor。。。");
    }


    /**
     * 销毁的时候执行
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        log.info("LifeBean4 destroy。。。");
    }

    /**
     * bean的属性设置完成之后执行
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("LifeBean4 afterPropertiesSet。。。");
    }

    @PostConstruct
    public void postConstruct(){
        log.info("LifeBean4 postConstruct。。。");
    }

    @PreDestroy
    public void preDestroy(){
        log.info("LifeBean4 preDestroy。。。");
    }

    public void init(){
        log.info("LifeBean4 init。。。");
    }

    public void destroyOnBean(){
        log.info("LifeBean4 destroyOnBean。。。");
    }
}
  1. 配置
@Configuration
@ComponentScan("study.wyy.spring.anno.life")
public class MainLiftCycleConfig {
    @Bean(initMethod = "init",destroyMethod = "destroyOnBean")
    public LifeBean4 lifeBean4(){
        return new LifeBean4();
    }
}
  1. 测试
  @Test
    public void test05(){
        // 创建ioc容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
        log.info("ioc容器创建完成。。。");
        LifeBean4 bean = applicationContext.getBean(LifeBean4.class);
        applicationContext.close();
    }
  1. 日志输出
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 postConstruct。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 afterPropertiesSet。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 init。。。
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 preDestroy。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 destroy。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 destroyOnBean。。。

可见初始化和销毁的时候这三个顺序:

  • @postConstruct
  • InitializingBean
  • @Bean

6 BeanPostProcessor

6.1 BeanPostProcessor介绍

可以对Spring容器扫描到的Bean在初始化前后进行增强处理

public interface BeanPostProcessor {

	/**
	 * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 */
	 /**
     *
     * @param bean : 当前的处理Bean
     * @param beanName 当前Bean的name
     * @return 可以返回当前的Bean也可以返回当前Bean的包装
     * @throws BeansException
     * 初始化(afterPropertiesSet,init-method)之前
     */
	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

	/**
	 * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
	 * instance and the objects created by the FactoryBean (as of Spring 2.0). The
	 * post-processor can decide whether to apply to either the FactoryBean or created
	 * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
	 * <p>This callback will also be invoked after a short-circuiting triggered by a
	 * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
	 * in contrast to all other BeanPostProcessor callbacks.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 * @see org.springframework.beans.factory.FactoryBean
	 */
	 /**
     *
     * @param bean 当前的处理Bean
     * @param beanName 当前Bean的name
     * @return 可以返回当前的Bean也可以返回当前Bean的包装
     * @throws BeansException
     * 初始化(afterPropertiesSet,init-method)之后
     */
	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

6.2 BeanPostProcessor测试

/*
 * @author :wyaoyao
 * @date : 2020-06-14 22:09
 * BeanPostProcessor:Bean初始化前后进行增强处理
 */
@Slf4j
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    /**
     *
     * @param bean : 当前的处理Bean
     * @param beanName 当前Bean的name
     * @return 可以返回当前的Bean也可以返回当前Bean的包装
     * @throws BeansException
     * 初始化之前
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof LifeBean4){
            log.info("lifeBean4 postProcessBeforeInitialization。。。");
        }
        return bean;
    }

    /**
     *
     * @param bean 当前的处理Bean
     * @param beanName 当前Bean的name
     * @return 可以返回当前的Bean也可以返回当前Bean的包装
     * @throws BeansException
     * 初始化之后
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof LifeBean4){
            log.info("lifeBean4 postProcessAfterInitialization。。。");
        }
        return bean;
    }
}

  1. 测试
@Test
    public void test05(){
        // 创建ioc容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
        log.info("ioc容器创建完成。。。");
        LifeBean4 bean = applicationContext.getBean(LifeBean4.class);
        applicationContext.close();
    }
  1. 日志
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 constructor。。。
[main] INFO study.wyy.spring.anno.life.config.MyBeanPostProcessor - lifeBean4 postProcessBeforeInitialization。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 postConstruct。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 afterPropertiesSet。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 init。。。
[main] INFO study.wyy.spring.anno.life.config.MyBeanPostProcessor - lifeBean4 postProcessAfterInitialization。。。
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 preDestroy。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 destroy。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 destroyOnBean。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值