BeanPostProcessor和Ordered

1. 概述

BeanPostProcessor 和 Ordered 接口用于在Spring容器初始化Bean的过程中进行自定义处理,并控制处理顺序

2. BeanPostProcessor

BeanPostProcessor 接口允许你在Spring容器初始化Bean的前后对Bean进行自定义处理。它有两个方法:

  • postProcessBeforeInitialization(Object bean, String beanName):在Bean初始化之前调用。
  • postProcessAfterInitialization(Object bean, String beanName):在Bean初始化之后调用。
    • bean:容器正在创建的那个bean的引用;
    • beanName:容器正在创建的那个bean的名称;

2.1 bean的生命周期

在这里插入图片描述

描述如下:

  1. 首先由Spring容器创建bean实例;
  2. 为bean的属性注入值;
  3. 若bean实现了各类Aware接口,则调用相应的set方法,
    • 比如说,实现了BeanNameAware接口的bean,此时容器将调用bean的setBeanName方法,将bean的name作为参数;
    • 实现了ApplicationContextAware接口的bean,此时容器将执行bean的setApplicationContext方法,将bean所在的上下文对象作为参数……
  4. 若容器中包含实现了BeanPostProcessor接口的bean,则此时将调用这些bean的postProcessBeforeInitialization方法,将当前正在创建的bean的引用以及bean的name作为参数传入;
  5. 若bean实现了InitializingBean接口,此时将调用bean的afterPropertiesSet方法;
  6. 若bean指定了自定义的初始化方法,比如说通过配置文件的init-method选项,则此时将执行这个自定义初始化方法;
  7. 若容器中包含实现了BeanPostProcessor接口的bean,则此时将调用这些bean的postProcessAfterInitialization方法,将当前正在创建的bean的引用以及bean的name作为参数传入;
    • 可以在一个容器中注册多个不同的BeanPostProcessor的实现类对象,而bean在创建的过程中,将会轮流执行这些对象实现的before和after方法
    • 执行顺序通过BeanPostProcessor的实现类实现这个Ordered接口,并实现接口的getOrder方法
  8. 这个时候,bean就算是初始化完毕,可以被使用了,在容器销毁之前,这个对象将一直保存在容器中;
  9. bean实现了DisposableBean接口,则在容器销毁时,会调用bean的destroy方法;
  10. 如果bean定义了自定义的销毁方法,则在容器销毁时,会调用这个自定义的销毁方法;
  11. 容器销毁成功,bean也被回收

2.2 使用注意

2.2.1 BeanPostProcessor依赖的bean,不会执行BeanPostProcessor的方法

当我们在BeanPostProcessor的实现类中,依赖了其他的bean,
那么被依赖的bean被创建时,将不会执行它所在的BeanPostProcessor实现类实现的方法

比如我们修改PostBean的实现,如下所示:

  • 容器在创建User这个bean时,不会执行PostBean实现的两个方法,
  • 因为由于PostBean依赖于user,所以user需要在PostBean之前创建完成,
  • 这也就意味着在user创建时,PostBean还未初始化完成,所以不会调用它的方法
@Component
public class PostBean implements BeanPostProcessor, Ordered {
    // 让PostBean依赖User
    @Autowired
    private User user;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) 
        throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) 
        throws BeansException {
        return bean;
    }
}

2.2.2 BeanPostProcessor以及依赖的bean无法使用AOP

Spring的AOP代理就是作为BeanPostProcessor实现的

所以我们无法对BeanPostProcessor的实现类使用AOP织入通知,

也无法对BeanPostProcessor的实现类依赖的bean使用AOP织入通知。

2.3 将BeanPostProcessor注册到Spring容器中

2.3.1 @Component注解

使用@Component注解:在实现类上添加@Component注解,这样Spring会自动扫描并注册这个bean。

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    // 实现方法
}

2.3.2 使用@Bean配置BeanPostProcessor的限制

使用Java配置类:如果你使用的是Java配置类,可以在配置类中注册这个bean。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

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

示例如下:


/**
 * 此BeanPostProcessor的实现类,还实现了Ordered接口
 */
public class PostBean implements BeanPostProcessor, Ordered {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("before -- " + beanName);
        return bean;
    }

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

    @Override
    public int getOrder() {
        return 0;
    }
}

在配置类中,声明PostBean可以有以下几种方式

  1. 只有第一种和第二种方式,会让Spring容器将PostBean当作BeanPostProcessor处理
  2. 而第三种方式,则会被当作一个普通Bean处理,实现BeanPostProcessor的两个方法都不会被调用,
    • 因为在PostBean的继承体系中,Ordered和BeanPostProcessor是同级别的,
    • Spring无法识别出这个Ordered对象,也是一个BeanPostProcessor对象;
    • 但是使用PostBean却可以,因为PostBean类型就是BeanPostProcessor的子类型
    • 所以,在使用@Bean声明工厂方法返回BeanPostProcessor实现类对象时,返回值必须是BeanPostProcessor类型,或者更低级的类型
    @Configuration
    public class BeanConfig {
    
        // 方式1:PostBean
        @Bean
        public PostBean postBean() {
            return new PostBean();
        }
    
        // 方式2:返回值为BeanPostProcessor
        @Bean
        public BeanPostProcessor postBean() {
            return new PostBean();
        }
    
        // 方式3:返回值为Ordered
        @Bean
        public Ordered postBean() {
            return new PostBean();
        }
    }
    

2.3.3 spring.factories

创建 BeanPostProcessor 实现类:

首先,创建一个实现 BeanPostProcessor 接口的类。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyAutoConfiguration {

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

创建自动配置类:创建一个自动配置类,并在其中定义 BeanPostProcessor 的 @Bean 方法

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyAutoConfiguration {

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

创建 spring.factories 文件:在 src/main/resources/META-INF/ 目录下创建 spring.factories 文件,并在其中添加自动配置类的全限定名

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration

目录结构

src/main/java/
    com/example/
        MyBeanPostProcessor.java
        MyAutoConfiguration.java
src/main/resources/
    META-INF/
        spring.factories

2.3.4 Xml

在XML中注册这个bean。

<bean id="myBeanPostProcessor" class="com.example.MyBeanPostProcessor"/>

3. Order

Ordered 接口用于控制多个 BeanPostProcessor 的执行顺序。它有一个方法:

  • getOrder():返回一个整数值,表示处理器的顺序。值越小,优先级越高。

4. 多个 BeanPostProcessor 的顺序

如果有多个 BeanPostProcessor,可以通过实现 Ordered 接口来控制它们的执行顺序。值越小,优先级越高。

5. 举例

自定义Bean后处理器

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

@Component
public class CustomBeanPostProcessor implements BeanPostProcessor, Ordered {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyService) {
            System.out.println("Before Initialization: " + beanName);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyService) {
            System.out.println("After Initialization: " + beanName);
        }
        return bean;
    }

    @Override
    public int getOrder() {
        return 1; // 优先级,值越小优先级越高
    }
}

服务类

import org.springframework.stereotype.Service;

@Service
public class MyService {
    public void serve() {
        System.out.println("Service method executed");
    }
}

主类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

另一个自定义Bean后处理器

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

@Component
public class AnotherBeanPostProcessor implements BeanPostProcessor, Ordered {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyService) {
            System.out.println("Another Before Initialization: " + beanName);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyService) {
            System.out.println("Another After Initialization: " + beanName);
        }
        return bean;
    }

    @Override
    public int getOrder() {
        return 2; // 优先级,值越小优先级越高
    }
}

运行示例

Before Initialization: myService
Another Before Initialization: myService
After Initialization: myService
Another After Initialization: myService
Service method executed
  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

?abc!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值