当前位置: 首页 > news >正文

Spring5学习笔记03--Bean的生命周期

内容概要:

  • Spring bean 生命周期各个阶段
  • 模版方法设计模式
  • Bean生命周期各个阶段,调用顺序: 构造 > 依赖注入 > 初始化 > 销毁
/**
 * 用于展示Bean生命周期各个阶段
 * 调用顺序: 构造 > 依赖注入 > 初始化 > 销毁
 */
@Slf4j
@Component
public class LifeCycleBean {

    public LifeCycleBean() {
        log.debug("构造 Construct");
    }

    @Autowired
    public void autowird(@Value("${JAVA_HOME}") String home) {
        log.debug("依赖注入 @Autowired : {}", home);
    }

    @PostConstruct
    public void init() {
        log.debug("初始化 @PostConstruct");
    }

    @PreDestroy
    public void destroy() {
        log.debug("销毁 @PreDestroy");
    }
}
  • 测试类
@SpringBootApplication
public class S03Application {

    public static void main(String[] args) {
        // 启动程序,返回Spring容器
        ConfigurableApplicationContext context = SpringApplication.run(S03Application.class, args);

        // 关闭容器
        context.close();
    }
}
  • 输出
构造 Construct
依赖注入 @Autowired : xxx/jdk1.8.0_261.jdk/Contents/Home/
初始化 @PostConstruct
销毁 @PreDestroy
  • 验证bean后处理器进行功能增强的时机
    • 自定义 MyBeanPostProcessor 实现 InstantiationAwareBeanPostProcessorDestructionAwareBeanPostProcessor
/**
 * bean后处理器进行功能增强的时机
 */
@Slf4j
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<<<< 实例化(构造)之前执行,如果返回的对象不为null,会替换掉原本的bean;返回null,保持原有不变");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<<<< 实例化(构造)之后执行,如果返回false,会跳过依赖注入阶段;返回true,不跳过");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<<<< 依赖注入阶段执行,一些Bean后处理器会在这里执行一些扩展功能,如 @Autowired @Value @Resource");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<<<< 初始化之前执行,返回的对象会替换调原本的bean, 如 @PostConstruct @ConfigurationProperties"); //@PostConstruct 虽然是Post 但是在初始化完成前执行
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<<<< 初始化之后执行,返回的对象会替换调原本的bean, 如代理增强");
        }
        return bean;
    }

    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<<<< 销毁之前执行, 如 @PreDestroy");
        }
    }

}

模版方法:静动结合

  • 静-固定不变的步骤

  • 动-需要回调的接口,不确定的逻辑抽象成接口

  • Bean后处理器采用的是模版方法设计模式来进行功能增强设计

    • 固定不变的形成主干,后续需要扩展的,抽象成接口
    • 这样后续加各种扩展功能,不需要对getBean()方法进行改动

使用模版方法自定义一个Bean后处理器

  • 主干逻辑
// 定义BeanFactory
public class MyBeanFactory {

  // getBean01() 方法每次添加功能都需要重写修改方法,不支持功能扩展
  public Object getBean01() {
    Object bean = new Object();
    System.out.println("构造 " + bean);
    System.out.println("依赖注入 " + bean);
    System.out.println("初始化 " + bean);
    return bean;
  }
}
  • 想要在Bean初始化之前添加一些功能,进行功能扩展

    • getBean01() 方法每次添加功能都需要重写修改方法

    • 将固定不变的部分形成主干逻辑

    • 在需要进行功能增加的地方,需要扩展的部分抽象为接口

  • 接口抽象

public interface BeanPostProcessor {
  // 对依赖注入阶段的扩展
  public void inject(Object bean);
}
  • 在需要进行功能增加的地方,调用接口进行扩展,同时对外提供添加功能扩展接口的入口
public class MyBeanFactory {
  // 定义Bean 后处理器的列表
  List<BeanPostProcessor> processors = new ArrayList<>();
  public Object getBean02() {
    Object bean = new Object();
    System.out.println("构造 " + bean);
    System.out.println("依赖注入 " + bean);

    // 依赖注入阶段的扩展
    for(BeanPostProcessor process : processors) {
      process.inject(bean);
    }

    System.out.println("初始化 " + bean);
    return bean;
  }

  // 对外提供添加Bean 后处理器的入口
  public void addBeanPostProcessor(BeanPostProcessor processor) {
    processors.add(processor);
  }
}

相关文章:

  • 在小熊派BearPi-HM_Micro_small开发板上安装HAP
  • 基数排序(学习)
  • hive窗口函数最全总结
  • Vulnhub靶场 ICA: 1
  • Tomcat部署
  • 大数据如何进行测试
  • python基础专栏13-python基础篇-控制结构
  • 3.4 创建共用模块-供其它模块使用
  • 通用Excel表格导出(Map类型数据导出为表格)
  • leetcode刷题 (9.1) 动态规划
  • 【C++】如何理解函数调用中的传值和传址
  • 糖尿病会隐身,这些信号一定要重视
  • 智能驾驶功能软件平台设计规范第五部分:定位功能服务接口
  • 框架阶段六:SpringCloud
  • 《effecttive C++》和一些其他C++开发的东西的学习总结(长期更新)
  • AWS实战 - 利用IAM对S3做访问控制
  • bootstrap创建登录注册页面
  • css布局,左右固定中间自适应实现
  • E-HPC支持多队列管理和自动伸缩
  • IOS评论框不贴底(ios12新bug)
  • Javascript Math对象和Date对象常用方法详解
  • javascript数组去重/查找/插入/删除
  • Linux下的乱码问题
  • tweak 支持第三方库
  • 测试如何在敏捷团队中工作?
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 前端自动化解决方案
  • 让你的分享飞起来——极光推出社会化分享组件
  • 学习使用ExpressJS 4.0中的新Router
  • 一个JAVA程序员成长之路分享
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • #Spring-boot高级
  • #单片机(TB6600驱动42步进电机)
  • (12)Hive调优——count distinct去重优化
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (C语言)二分查找 超详细
  • (function(){})()的分步解析
  • (九)c52学习之旅-定时器
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (四)库存超卖案例实战——优化redis分布式锁
  • (算法)Travel Information Center
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转)重识new
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .gitignore文件设置了忽略但不生效
  • .md即markdown文件的基本常用编写语法
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET 常见的偏门问题
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • .NET/C# 中设置当发生某个特定异常时进入断点(不借助 Visual Studio 的纯代码实现)
  • .net开发引用程序集提示没有强名称的解决办法
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • .pings勒索病毒的威胁:如何应对.pings勒索病毒的突袭?
  • //解决validator验证插件多个name相同只验证第一的问题