随笔 - 1162  文章 - 0  评论 - 16  阅读 - 59万 

一、Bean 的生命周期

Bean 的生命周期是指:bean 创建 ---> 初始化 ---> 销毁的过程
Spring 中是由 IOC 容器管理 bean 的生命周期,我们可以自定义初始化和销毁方法,
容器在 bean 进行到当前生命周期的时候来调用我们自定义初始化方法和销毁方法。

1、构造方法(对象创建)
  单实例:在容器启动的时候创建对象;
  多实例:每次获取的时候创建对象;

2、初始化方法
  单实例:对象创建完成,并赋值好,调用初始化方法。
  多实例bean:在创建的时候调用;

3、销毁方法
  单实例:容器关闭的时候,销毁对象;
  多实例:容器不会管理整个bean,在需要的时候负责创建,容器不会调用销毁方法。

实现方式:

方式一:指定初始化和销毁方法
  通过 @Bean 指定 init-method 和 destory-method 方法


方式二:通过让 Bean 实现 InitializingBean(定义初始化逻辑) 和 DisposableBean(定义销毁逻辑) 这两个接口,然后重写其中的方法。


方式三:使用 JSR250规范中的注解
  在方法上使用注解来进行说明。
    @PostConstruct:在 bean创建完成并且属性赋值完成,来执行初始化方法,在方法上
    @PreDestroy:在容器销毁 bean之前通知我们进行清理工作

  使用 BeanPostProcessor bean的后置处理器
    postProcessBeforeInitialization:在初始化之前工作
    postProcessAfterInitialization:在初始化之后工作

二、方式一:@Bean 注解指定方法

使用 @Bean 注解指定初始化和销毁方法;

原来是在配置文件的 bean 标签中使用 init-method 和 destory-method 来指定方法。

现在可以在配置类中通过 @Bean 注解中的 initMethod 和 destoryMethod 来指定方法:

声明 Car 类:

public class Car {

    public Car() {
        System.out.println("Car  constructor...");
    }

    public void init() {
        System.out.println("Car ... init...");
    }

    public void destory() {
        System.out.println("Car ... destory...");
    }

}

配置类:

@Configuration
public class MainConfigOfLifeCycle {

    @Bean(initMethod = "init", destroyMethod = "destory")
    public Car getCar() {
        return new Car();
    }

}

测试:

    @Test
    public void test01() {
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);

        System.out.println("IOC容器创建完毕");

        ioc.close();
    }

三、方式二:实现接口

通过让 Bean 实现 InitializingBean(定义初始化逻辑) 和 DisposableBean(定义销毁逻辑) 这两个接口,然后重写其中的方法。

声明 Cat 类:

public class Cat implements InitializingBeanDisposableBean {

    public Cat() {
        System.out.println("cat constructor");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("cat ... afterPropertiesSet ...");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("cat ... destory ...");
    }

}

配置类:

@Configuration
public class MainConfigOfLifeCycle {

    @Bean
    public Cat getCat() {
        return new Cat();
    }

}

四、方式三

使用 JSR250 规范中的注解,在方法上面使用注解来进行说明:

@PostConstruct:在 bean 创建完成并且属性赋值完成,来执行初始化方法,在方法上

@PreDestroy:在容器销毁 bean 之前通知我们进行清理工作

声明 Dog 类:

public class Dog {

    public Dog() {
        System.out.println("Dog constructor");
    }

    //对象创建并赋值之后调用
    @PostConstruct
    public void init() {
        System.out.println("Dog....@PostConstruct。。。");
    }

    //容器移除对象之前
    @PreDestroy
    public void destory() {
        System.out.println("Dog....@PreDestroy。。。");
    }

}

配置类:

@Configuration
public class MainConfigOfLifeCycle {

    @Bean
    public Dog getDog() {
        return new Dog();
    }

}

测试:

五、方式四:BeanPostProcessor 后置处理器

使用 BeanPostProcessor bean 的后置处理器

postProcessBeforeInitialization:在初始化之前工作

postProcessAfterInitialization:在初始化之后工作

定义 Bean 的后置处理器:

/**
 * 后置处理器:初始化前后进行处理工作
 * 将后置处理器加入到容器中
 */
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization" +  beanName + "=>" + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization" +  beanName + "=>" + bean);
        return bean;
    }
}

将后置处理器添加到容器中:

@Configuration
public class MainConfigOfLifeCycle {

    @Bean
    public Dog getDog() {
        return new Dog();
    }

    @Bean
    public MyBeanPostProcessor getMyBeanPostProcessor() {
        return new MyBeanPostProcessor();
    }

}

测试:

六、BeanPostProcessor 原理

源码 DeBug:【AbstractAutowireCapableBeanFactory】

流程:

populateBean(beanName, mbd, instanceWrapper);给 bean 进行属性赋值

initializeBean
{
  applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
  applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

遍历得到容器中所有的 BeanPostProcessor;挨个执行 beforeInitialization。

一但返回 null,跳出 for 循环,不会执行后面的 BeanPostProcessor.postProcessorsBeforeInitialization

Spring 底层对 BeanPostProcessor 的使用:

① ApplicationContextAwareProcessor:用于向 bean 组件中添加 ioc 容器;

② BeanValidationPostProcessor:用于数据的校验工作;

③ InitDestroyAnnotationBeanPostProcessor:用于解析 @PostConstruct 和 @PreDestory 注解

④ AutowiredAnnotationBeanPostProcessor:解析 @Autowired 注解,来注入其他组件;

Spring 中提供了一系列的 BeanPostProcessor,可以用于给 bean 赋值,注入其他组件,还有的用来解析 @Autowired 注解,解析生命周期注解功能的多样的 BeanPostProcessor。

posted on   格物致知_Tony  阅读(113)  评论(0编辑  收藏  举报
编辑推荐:
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· 面试官:你是如何进行SQL调优的?
点击右上角即可分享
微信分享提示

目录导航