• 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");
        }
    }
    
    • 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
    • 测试类
    @SpringBootApplication
    public class S03Application {
    
        public static void main(String[] args) {
            // 启动程序,返回Spring容器
            ConfigurableApplicationContext context = SpringApplication.run(S03Application.class, args);
    
            // 关闭容器
            context.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 输出
    构造 Construct
    依赖注入 @Autowired : xxx/jdk1.8.0_261.jdk/Contents/Home/
    初始化 @PostConstruct
    销毁 @PreDestroy
    
    • 1
    • 2
    • 3
    • 4
    • 验证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");
            }
        }
    
    }
    
    • 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
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    模版方法:静动结合

    • 静-固定不变的步骤

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

    • 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;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 想要在Bean初始化之前添加一些功能,进行功能扩展

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

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

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

    • 接口抽象

    public interface BeanPostProcessor {
      // 对依赖注入阶段的扩展
      public void inject(Object bean);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 在需要进行功能增加的地方,调用接口进行扩展,同时对外提供添加功能扩展接口的入口
    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);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    hive数据库delete删除部分数据/删除分区内的数据
    Matlab中关于 : 的使用
    webgl计算包围盒大小
    基于Conda的PyTorch Geometric报“段错误 (核心已转储)”的解决方法
    树莓派串口通信常用函数
    golang工程中间件——redis常用结构及应用(string, hash, list)
    (2022牛客多校四)A-Task Computing (排序+动态规划)
    【TS】类和接口
    【阿里云】函数计算 X 通义千问快速部署
    低代码平台那些事儿
  • 原文地址:https://blog.csdn.net/qingqingxiangyang/article/details/126667187