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

yizhihongxing

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日

相关文章

  • Mysql 安装及my.ini的创建过程

    MySQL是一款常用的关系型数据库管理系统,本文将介绍如何安装MySQL并创建my.ini配置文件。 安装MySQL 下载MySQL安装包 如需下载安装包,请前往官网选择适合自己系统的版本。 安装MySQL 打开安装包,按照提示页面进行操作。在MySQL Installer中,选择完整型安装,以获得最常用的MySQL组件。 配置MySQL 在安装程序中的“T…

    other 2023年6月27日
    00
  • Windows远程数据、文件同步工具cwRsync配置方法

    Windows 远程数据、文件同步工具 cwRsync 配置方法 cwRsync 是 Windows 上的一款远程同步工具,可以实现 Windows 与 Linux 或 Unix 等不同系统之间的文件同步,也可以实现 Windows 与 Windows 之间的文件同步。本文将详细讲解 cwRsync 的配置方法。 1. 下载和安装 cwRsync 你可以在 …

    other 2023年6月25日
    00
  • tar命令基本使用(加密)

    以下是详细讲解“tar命令基本使用(加密)”的完整攻略,过程中至少包含两条示例说明的标准Markdown格式文本: tar命令基本使用(加密) tar命令是Linux系统中用的压缩和打包工具,它可以将多个文件或目录打包成一个文件,并可以对打包文件进行压缩和加密。文将介绍tar命令的基本使用和加密功能。 基本使用 在Linux系统中,可以使用tar命令将多个文…

    other 2023年5月10日
    00
  • 在android中将string转换为int

    以下是关于“在Android中将String转换为int”的完整攻略,包含两个示例。 在Android中将String转换为int 在Android开发中,我们经常需要将String类型的数据转换为int类型。以下是关于如何在Android中将String转换为int的详细攻略。 1. 使用Integer.parseInt()方法 在Android中,我们可…

    other 2023年5月9日
    00
  • IDEA设置JVM可分配内存大小和其他参数的教程

    下面是详细的攻略: 1. 打开IDEA的配置页面 首先,我们需要打开IDEA的配置页面。在主窗口中,点击顶部菜单栏中的 “File” 菜单,然后选择 “Settings”。如果你使用的是Mac系统,可以选择 “Preferences” 而不是 “Settings”。 2. 配置JVM的参数 在设置页面中,找到 “Build, Execution, Deplo…

    other 2023年6月27日
    00
  • SQL2008中SQL应用之- 死锁(Deadlocking)

    SQL2008中SQL应用之死锁(Deadlocking)攻略 在 SQL2008 中,死锁是指两个或多个事务相互等待,导致所有事务无法继续执行的状态。 死锁的原因 死锁通常发生在多个事务同时访问同一资源时。例如,如果两个事务同时想要更新同一个表中的同一行,其中一个事务必须等待另一个事务完成才能继续执行。如果两个事务都在等待对方完成,就会发生死锁。 防止死锁…

    other 2023年6月27日
    00
  • SpringBoot整合websocket实现即时通信聊天

    下面是详细讲解SpringBoot整合websocket实现即时通信聊天的攻略。 1. 环境准备 首先,我们需要准备好以下环境: JDK 1.8及以上版本 Maven Spring Boot 2.0.3.RELEASE及以上版本 2. 添加依赖 在pom.xml文件中添加以下依赖: <dependency> <groupId>org.…

    other 2023年6月27日
    00
  • Python面向对象编程之继承与多态详解

    Python面向对象编程之继承与多态详解 1. 继承 继承是面向对象编程中的一个重要概念,它允许子类继承父类的属性和方法。在 Python 中,我们可以通过以下方式来实现继承: class Person: def __init__(self, name, age): self.name = name self.age = age def introduce(…

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