第三讲-Bean的生命周期和模板方法

第三讲 Bean的生命周期和模板方法

1. Spring 生命周期的各个阶段

首先准备好一个Spring容器:

@SpringBootApplication
public class A03Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(A03Application.class, args);
        context.close();
    }
}

准备一个Bean:

package com.cherry.chapter1.a03;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class LifeCycleBean {
    private static final Logger log = LoggerFactory.getLogger(LifeCycleBean.class);

    public LifeCycleBean(){
        log.debug("构造方法被调用");
    }

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

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

    @PreDestroy
    public void destroy(){
        log.debug("销毁");
    }
}

接下来我们启动程序,查看运行结果:

2024-07-21 11:11:50.641 DEBUG 17064 --- [           main] com.cherry.chapter1.a03.LifeCycleBean    : 构造方法被调用
2024-07-21 11:11:50.644 DEBUG 17064 --- [           main] com.cherry.chapter1.a03.LifeCycleBean    : 依赖注入:D:\development_tools\jdk17\jdk-17.0.10
2024-07-21 11:11:50.646 DEBUG 17064 --- [           main] com.cherry.chapter1.a03.LifeCycleBean    : 初始化
2024-07-21 11:11:50.941  WARN 17064 --- [           main] o.s.b.a.f.FreeMarkerAutoConfiguration    : Cannot find template location(s): [classpath:/templates/] (please add some templates, check your FreeMarker configuration, or set spring.freemarker.checkTemplateLocation=false)
2024-07-21 11:11:50.976  INFO 17064 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2024-07-21 11:11:50.984  INFO 17064 --- [           main] com.cherry.chapter1.a03.A03Application   : Started A03Application in 1.642 seconds (JVM running for 2.613)
2024-07-21 11:11:51.248 DEBUG 17064 --- [           main] com.cherry.chapter1.a03.LifeCycleBean    : 销毁

我们可以看到,执行的流程如下:

  1. 首先执行Bean的构造方法
  2. 其次执行Bean的依赖注入方法
  3. 紧接着执行Bean的初始化方法
  4. 最后执行Bean的销毁方法

前面我们讲过,Bean后处理器是对Bean生命周期各个阶段的一些扩展,那都有哪些扩展呢?这里举一些例子:

package com.cherry.chapter1.a03;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;

@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
    private static final Logger log = LoggerFactory.getLogger(MyBeanPostProcessor.class);



    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("<<<< 实例化之前执行,构造方法之前执行");
        }
        return null;
    }


    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("<<<< 实例化之后执行,构造方法执行完毕之后执行");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("<<<< 依赖注入阶段执行.如@Autowird,@Value,@Resource");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("<<<< 初始化之前执行,这里返回的对象会替换掉原本的bean, 如@PostConstruct, 2ConfigurationProperties");
        }
        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("<<<< 销毁前执行,如@PreDestory");
        }
    }
}

执行结果如下:

2024-07-21 11:43:30.492 DEBUG 6504 --- [           main] c.c.chapter1.a03.MyBeanPostProcessor     : <<<< 实例化之前执行,构造方法之前执行
2024-07-21 11:43:30.493 DEBUG 6504 --- [           main] com.cherry.chapter1.a03.LifeCycleBean    : 构造方法被调用
2024-07-21 11:43:30.496 DEBUG 6504 --- [           main] c.c.chapter1.a03.MyBeanPostProcessor     : <<<< 实例化之后执行,构造方法执行完毕之后执行
2024-07-21 11:43:30.496 DEBUG 6504 --- [           main] c.c.chapter1.a03.MyBeanPostProcessor     : <<<< 依赖注入阶段执行.如@Autowird,@Value,@Resource
2024-07-21 11:43:30.497 DEBUG 6504 --- [           main] com.cherry.chapter1.a03.LifeCycleBean    : 依赖注入:D:\development_tools\jdk17\jdk-17.0.10
2024-07-21 11:43:30.498 DEBUG 6504 --- [           main] c.c.chapter1.a03.MyBeanPostProcessor     : <<<< 初始化之前执行,这里返回的对象会替换掉原本的bean, 如@PostConstruct, 2ConfigurationProperties
2024-07-21 11:43:30.498 DEBUG 6504 --- [           main] com.cherry.chapter1.a03.LifeCycleBean    : 初始化
2024-07-21 11:43:30.498 DEBUG 6504 --- [           main] c.c.chapter1.a03.MyBeanPostProcessor     : <<<< 依赖注入阶段执行,这里返回的对象会替换掉原本的bean,如代理增强
2024-07-21 11:43:30.840  WARN 6504 --- [           main] o.s.b.a.f.FreeMarkerAutoConfiguration    : Cannot find template location(s): [classpath:/templates/] (please add some templates, check your FreeMarker configuration, or set spring.freemarker.checkTemplateLocation=false)
2024-07-21 11:43:30.884  INFO 6504 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2024-07-21 11:43:30.892  INFO 6504 --- [           main] com.cherry.chapter1.a03.A03Application   : Started A03Application in 1.932 seconds (JVM running for 3.291)
2024-07-21 11:43:31.166 DEBUG 6504 --- [           main] c.c.chapter1.a03.MyBeanPostProcessor     : <<<< 销毁前执行,如@PreDestory
2024-07-21 11:43:31.167 DEBUG 6504 --- [           main] com.cherry.chapter1.a03.LifeCycleBean    : 销毁

2. 模板设计模式 Template Method Pattern

举个例子:

package com.cherry.chapter1.a03;

import java.util.ArrayList;
import java.util.List;

public class TesttemplateMethod {
    public static void main(String[] args) {
        MyBeanFactory beanFactory = new MyBeanFactory();
        beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Autowired"));
        beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Resource"));
        beanFactory.getBean();
    }

    // 模板方法 Template Method Pattern
    static class MyBeanFactory{
        public Object getBean(){
            Object bean = new Object();
            System.out.println("构造 "+bean);
            System.out.println("依赖注入 "+bean);
            for (BeanPostProcessor bp:processors){
                bp.inject(bean);
            }

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

        private List<BeanPostProcessor> processors = new ArrayList<>();

        public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor){
            processors.add(beanPostProcessor);
        }
    }

    static interface BeanPostProcessor {
        public void inject(Object bean);   // 对依赖注入阶段的扩展

    }
}

运行结果如下:

构造 java.lang.Object@4b6995df
依赖注入 java.lang.Object@4b6995df
解析 @Autowired
解析 @Resource
初始化 java.lang.Object@4b6995df

模板方法的核心就是将不能确定的部分抽象为一个接口,将来在特定的时机调用抽象方法,通过回调的方式对接口中的功能进行扩展。

posted @   LilyFlower  阅读(5)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示