Spring生命周期回调与容器扩展详解

Spring生命周期回调与容器扩展详解

在Spring框架中,Bean的生命周期回调与容器扩展是非常重要的一部分。Spring框架有一个完整的标准初始化和销毁Bean的流程, 我们可以根据自己的业务需求去扩展这个流程,实现一些自定义的处理。

Bean的生命周期回调

在Spring中,一个Bean的创建与销毁都是由容器来管理的, 容器会自动的调用Bean的一些方法来完成Bean的初始化和销毁。我们可以在Bean的生命周期的多个阶段插入我们自己的处理逻辑。这些阶段包括:Bean实例化、Bean属性设置、Bean初始化前、Bean初始化后、容器销毁前和容器销毁后等。

Bean实例化

在Bean实例化阶段,Spring会通过调用Bean的构造方法来实例化一个对象。如果Bean类的构造方法中存在参数,则Spring会先通过它们来实例化出所需的参数,并进行递归实例化。接着Spring会调用Bean实例化回调接口:InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation方法,以便让用户在Bean实例化之前进行一些处理。如果该方法返回了非 null 的 Bean,则 Spring 容器将不再调用它后面的 Bean 构造方法,直接使用返回的 Bean 对象。如果该方法返回了 null,则 Spring 容器仍会继续进行 Bean 的构造方法调用,直到构造出实例为止。

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("InstantiationAwareBeanPostProcessor postProcessBeforeInstantiation");
        }
        return null;
    }
}

@Configuration
@ComponentScan("com.example.demo")
public class AppConfig {
    @Bean
    public MyInstantiationAwareBeanPostProcessor myInstantiationAwareBeanPostProcessor() {
        return new MyInstantiationAwareBeanPostProcessor();
    }
}

Bean属性设置

在Bean属性设置阶段,Spring会调用Bean的setter方法来完成依赖注入。Spring通过反射机制查找 Bean 中特定的 set 方法,并将配置文件或者注释配置中所定义的属性值通过这些set方法进行注入。如果Bean实现了BeanNameAware接口或BeanFactoryAware接口,则在属性注入完成后,Spring容器会调用相应的回调方法:BeanNameAware#setBeanName()或BeanFactoryAware#setBeanFactory()。

public class User implements BeanNameAware, BeanFactoryAware {
    private String name;
    private int age;

    public void setBeanName(String name) {
        System.out.println(this.getClass().getSimpleName() + " setBeanName");
    }

    public void setBeanFactory(BeanFactory beanFactory) {
        System.out.println(this.getClass().getSimpleName() + " setBeanFactory");
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

@Configuration
@ComponentScan("com.example.demo")
public class AppConfig {
    @Bean
    public User user() {
        User user = new User();
        user.setName("Nate");
        user.setAge(30);
        return user;
    }
}

Bean初始化前

在Bean初始化前阶段,Spring容器会调用BeanPostProcessor#postProcessBeforeInitialization()该回调方法,让用户可以在Bean初始化的前面添加自己的逻辑。 Spring容器必须在Bean属性注入完成后,Bean实现了Aware的回调方法后,才会回调这个 BeanPostProcessor 的回调方法。这可以保证调用之前的 Bean 所有属性都被正确的设置了。

public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("BeanPostProcessor postProcessBeforeInitialization");
        }
        return bean;
    }
}

@Configuration
@ComponentScan("com.example.demo")
public class AppConfig {
    @Bean
    public MyBeanPostProcessor myBeanPostProcessor() {
        return new MyBeanPostProcessor();
    }
}

Bean初始化后

在Bean初始化后阶段,Spring容器会调用BeanPostProcessor#postProcessAfterInitialization()该回调方法,让用户可以在Bean初始化的后面添加自己的逻辑。 Spring容器必须在调用BeanPostProcessor#postProcessBeforeInitialization()之后,才会回调这个 BeanPostProcessor 的回调方法。

public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("BeanPostProcessor postProcessAfterInitialization");
        }
        return bean;
    }
}

@Configuration
@ComponentScan("com.example.demo")
public class AppConfig {
    @Bean
    public MyBeanPostProcessor myBeanPostProcessor() {
        return new MyBeanPostProcessor();
    }
}

容器销毁前

在容器销毁前阶段,Spring容器会调用DisposableBean#destroy()方法和DestroyBean接口的destroy()方法,以便进行Bean销毁前的一些逻辑处理。

public class Dog implements DisposableBean {
    public void destroy() throws Exception {
        System.out.println("DisposableBean destroy");
    }
}

@Configuration
@ComponentScan("com.example.demo")
public class AppConfig {
    @Bean(destroyMethod = "destroy")
    public Dog dog() {
        return new Dog();
    }
}

容器销毁后

在容器销毁后阶段,Spring容器会调用BeanPostProcessor#postProcessBeforeDestruction()方法和DestroyBean接口的destroy()方法,以便进行销毁Bean后的一些逻辑处理。

public class MyDestructionAwareBeanPostProcessor implements DestructionAwareBeanPostProcessor {
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("DestructionAwareBeanPostProcessor postProcessBeforeDestruction");
        }
    }

    public boolean requiresDestruction(Object bean) {
        return true;
    }
}

@Configuration
@ComponentScan("com.example.demo")
public class AppConfig {
    @Bean
    public MyDestructionAwareBeanPostProcessor myDestructionAwareBeanPostProcessor() {
        return new MyDestructionAwareBeanPostProcessor();
    }
}

容器扩展

在Spring中,我们还可以通过继承一些扩展点的抽象类来实现我们自己的扩展。这些扩展点包括:BeanFactoryPostProcessor、BeanPostProcessor、ApplicationListener和ResourceLoaderAware等。

BeanFactoryPostProcessor

BeanFactoryPostProcessor用于对BeanFactory进行处理。在Spring容器初始化完成之后,BeanFactory 调用BeanFactoryPostProcessor回调函数对BeanFactory进行外部扩展。我们可以通过实现这个接口实现对Bean的修改,比如替换Bean的内容,增加Bean的内容等等。注意:这个扩展只是针对BeanFactory的扩展,而不是Bean的扩展。

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition bd = beanFactory.getBeanDefinition("dog");
        MutablePropertyValues pvs = bd.getPropertyValues();
        if (pvs.contains("name")) {
            PropertyValue pv = pvs.getPropertyValue("name");
            pv.setConvertedValue("Tommy");
        }
    }
}

@Configuration
@ComponentScan("com.example.demo")
public class AppConfig {
    @Bean
    public MyBeanFactoryPostProcessor myBeanFactoryPostProcessor() {
        return new MyBeanFactoryPostProcessor();
    }
}

BeanPostProcessor

前面已经讲解了BeanPostProcessor,它主要用于在Bean的初始化前后添加自己的处理逻辑。

ApplicationListener

ApplicationListener用于监听ApplicationEvent类型的事件。当相关事件发生时,Spring容器就会调用该接口的回调函数。我们可以利用这个机制自定义自己需要的事件,并在事件发生时实现自己的业务逻辑。

public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {
    public void onApplicationEvent(MyApplicationEvent event) {
        System.out.println("MyApplicationListener onApplicationEvent");
    }
}

@Configuration
@ComponentScan("com.example.demo")
public class AppConfig {
    @Bean
    public MyApplicationListener myApplicationListener() {
        return new MyApplicationListener();
    }
}

public class MyApplicationEvent extends ApplicationEvent {
    public MyApplicationEvent(Object source) {
        super(source);
    }
}

@Component
public class User {
    @Autowired
    private ApplicationContext applicationContext;

    public void print() {
        MyApplicationEvent event = new MyApplicationEvent(this);
        applicationContext.publishEvent(event);
    }
}

ResourceLoaderAware

ResourceLoaderAware用于在加载Bean时获取ResourceLoader(资源加载器)来加载文件或URL等资源。

public class MyResourceLoaderAware implements ResourceLoaderAware {
    private ResourceLoader resourceLoader;

    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    public void print() throws IOException {
        Resource resource = resourceLoader.getResource("classpath:test.txt");
        InputStream inputStream = resource.getInputStream();
        System.out.println(inputStream);
    }
}

@Configuration
@ComponentScan("com.example.demo")
public class AppConfig {
    @Bean
    public MyResourceLoaderAware myResourceLoaderAware() {
        return new MyResourceLoaderAware();
    }
}

总结

Spring中的Bean生命周期回调和容器扩展提供了很好的扩展机制, 通过实现一些扩展点的接口,我们可以在Bean的实例化,初始化,销毁的不同阶段插入我们自己的处理逻辑,实现一些自定义的处理。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring生命周期回调与容器扩展详解 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 解析layoutsubviews

    解析layoutSubviews 在程序开发中,UIView 是我们经常使用的一个基础类。对于 UIView 的布局我们常常使用的是 autoresizingMask 或者是 constraint。但是在我们布局完毕之后,系统是如何将他们渲染到屏幕上的呢? 这里就需要了解 layoutSubviews 这个方法。layoutSubviews 是 UIView…

    其他 2023年3月29日
    00
  • linux btrfs文件系统及管理

    Linux Btrfs文件系统及管理攻略 什么是Btrfs文件系统? Btrfs是一个先进的复制文件系统,可以提供高容错性、数据集成、压缩和快照等功能。Btrfs文件系统还可以进行在线数据恢复和磁盘故障检测与修复。 如何安装Btrfs Btrfs作为Linux的核心文件系统,通常在大多数Linux发行版上默认安装。如果您需要安装,可以使用以下命令来检查是否安…

    other 2023年6月27日
    00
  • 使用CSS自定义属性实现骨架屏效果

    使用CSS自定义属性可以实现骨架屏效果,使页面在加载过程中展示一个简单的占位符,提高用户体验。 1. CSS自定义属性 CSS自定义属性是用来保存一些可以在多处使用的值的变量,其语法如下: element { –variable-name: value; } 其中element是指应用了该变量的元素,–variable-name表示自定义变量的名称,va…

    other 2023年6月25日
    00
  • deepqnetwork(dqn)原理解析

    Deep Q Network (DQN)原理解析 Deep Q Network (DQN)是一种可以将深度学习应用于强化学习的算法,由Google DeepMind公司在2015年提出。DQN旨在解决传统Q学习中状态空间过大的问题,在一定程度上缓解了强化学习中的稀疏奖励和延迟奖励问题。 Q-Learning 与 DQN DQN是基于Q-learning的改进…

    其他 2023年3月28日
    00
  • Linux宕机最安全的重启方法(你肯定不知道)

    Linux宕机最安全的重启方法(你肯定不知道) 背景 Linux操作系统在运行过程中,由于各种原因可能会出现宕机的情况,这时候需要进行重启操作。在重启操作时,如果不正确处理,可能会造成数据丢失、文件系统损坏等后果,因此重启方法的选择非常重要。 解决方案 下面是几种安全可靠的Linux宕机重启方法: 1. 快捷键重启 当Linux操作系统宕机时,我们可以通过按…

    other 2023年6月26日
    00
  • 如何降级cuda版本

    以下是关于如何降级CUDA版本的完整攻略,包括基本知识和两个示例说明。 基本知识 在降级CUDA版本之前,您需要了解以下基本知识: CUDA Toolkit:CUDA Toolkit是一个用于开发和优化CUDA应用程序的软件包,其中包括CUDA驱动程序和CUDA运行时库。 CUDA驱动程序:CUDA驱动程序是一个用于与GPU通信的软件组件它负责管理GPU的硬…

    other 2023年5月7日
    00
  • Android创建外部lib库及自定义View的图文教程

    让我来详细讲解一下“Android创建外部lib库及自定义View的图文教程”的完整攻略。 标准的库项目结构 要创建一个外部lib库,我们需要保证项目结构正确。一个典型的库项目结构如下: library/ src/ main/ java/ com/yourpackage/library/ LibraryClass.java res/ values/ attr…

    other 2023年6月25日
    00
  • Highchart基础教程-图表的主要组成

    下面是“Highchart基础教程-图表的主要组成的完整攻略”,包括图表的主要组成、使用方法、两个示例说明等方面。 图表的主要组成 Highchart是一个基于JavaScript的图表库,它可以用来创建各种类型的图表,包括线图、柱状图、饼图等。一个Highchart图表主要由以下几个组成部分: 标题:用于描述图表的主题或主要内容。 坐标轴:用于显示数据的坐…

    other 2023年5月5日
    00
合作推广
合作推广
分享本页
返回顶部