Bean生命周期

Bean生命周期

1.bean自身的生命周期

  1. 构造方法
  2. 依赖注入
  3. 初始化
  4. 销毁

代码实例如下(注意这只是模拟,实际上已经被增强bean后处理解析过):

@Component
@Slf4j
public class LifeCycleBean {

    //Bean自身的构造方法
    public LifeCycleBean(){
        log.info("构造方法");
    }

    //Bean依赖注入
    //使用Value注解,此时注入的不是Bean,而是配置参数或者是环境变量中的值
    @Autowired
    public void autowired(@Value("${JAVA_HOME}") String name){
        log.info("依赖注入,环境变量名{}",name);
    }

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

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

注意需要再启动类中使用close方法销毁bean,才能看到销毁周期

代码如下:

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

2.Bean生命周期加强

使用bean后处理器可以对bean的生命周期中进行增强操作

需要实现PostProcessor的子接口

以实例化和销毁接口为例,需要实现InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor接口中的方法

@Slf4j
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
    @Override
    // 实例化前(即调用构造方法前)执行的方法
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean"))
            log.debug("<<<<<<<<<<< 实例化前执行,如@PreDestroy");
        // 返回null保持原有对象不变,返回不为null,会替换掉原有对象
        return null;
    }

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

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

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

    @Override
    // 初始化之前执行的方法
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("lifeCycleBean"))
            log.debug("<<<<<<<<<<< 初始化之前执行,这里返回的对象会替换掉原本的bean,如 @PostConstruct、@ConfigurationProperties");
        return bean;
    }

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

注意:这里的方法优先级会比注解的优先级要高,因为就是这些增强方法实现解析注解

3.模板设计方法

在Spring 中 Bean的生命周期添加Bean后处理器的过程用到了模板设计方法:

模板方法设计模式是一种行为设计模式,它定义了一个算法的骨架,将一些步骤交给子类实现。

**核心思想:**定义一个算法的骨架,而将一些步骤延迟到子类中实现。这样可以在不改变算法结构的情况下,通过不同的子类来实现算法的不同行为。

**实现:**通常由一个抽象类来实现,该抽象类中包含了算法的骨架,以及一些步骤的具体实现。这些具体实现可以在抽象类中定义为抽象方法,以便在子类中实现。在模板方法模式中,算法的骨架由抽象类控制,而具体实现则由子类提供。

**优点:**可以在不改变算法结构的情况下,通过不同的子类来实现算法的不同行为。这样可以提高代码的复用性,同时也可以减少代码的重复编写。

在本例中就是不改变Bean其他生命周期实现,只在依赖注入的过程中添加Bean后处理程序,模拟进行@Autowired和@Resource等注解的解析


public class TestMethodTemplatePattern {
    public static void main(String[] args) {
        MyBeanFactory beanFactory = new MyBeanFactory();
       /* beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public void inject(Object bean) {
                System.out.println("解析 @Autowired");

            }
        });*/
        //后置处理器实现Bean生命周期功能增强
        beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Autowired"));
        beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Resource"));

        beanFactory.getBean();

    }

    static class MyBeanFactory {
        public Object getBean() {
            Object bean = new Object();
            System.out.println("构造" + bean);
            System.out.println("依赖注入" + bean);
            //使用Bean后处理器进行增强
            for (BeanPostProcessor processor : processors) {
                processor.inject(bean);
            }
            System.out.println("初始化" + bean);
            return bean;
        }
        private List<BeanPostProcessor> processors = new ArrayList<>();

        //在程序执行过程中会添加bean后置处理器
        public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor){
            processors.add(beanPostProcessor);
        }
    }


    //bean后处理器是接口只有一个抽象函数(public abstract可省略)
    //函数式接口
    interface BeanPostProcessor {
        void inject(Object bean);
    }
}


函数式接口的要求如下:

  1. 接口只有一个抽象方法
  2. 可以有默认方法和静态方法,但不会影响接口的函数式特性
  3. 可以有Object类的公共方法(如equals、hashCode等),但不会影响接口的函数式特性
  4. 注解@FunctionalInterface可以用于强制检查接口是否符合函数式接口的要求
  5. 函数式接口可以用lambda表达式、方法引用等方式实现,从而实现函数式编程的特性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值