Spring系列14:IoC容器的扩展点
回顾
知识需要成体系地学习,本系列文章前后有关联,建议按照顺序阅读。上一篇我们详细介绍了Spring Bean的生命周期和丰富的扩展点,没有阅读的强烈建议先阅读。本篇来详细讲讲容器提供的扩展点,完整的生命周期图镇楼。
本文内容
- 详解BeanPostProcessor
- 详解
BeanFactoryPostProcessor
- 详解
FactoryBean
详解BeanPostProcessor
作用和定义
常规 BeanPostProcessor 的作用是提供自定义的实例化逻辑、初始化逻辑、依赖关系解析逻辑等,对bean进行增强。主要的作用阶段是初始阶段前后。该接口定义了2接口,分别是前置增强和后置增强。 Spring AOP 功能主要是通过 BeanPostProcessor 实现的。
public interface BeanPostProcessor {
// 在任何 bean 初始化回调(如 InitializingBean 的 afterPropertiesSet 或自定义 init 方法)之前 // 将此 BeanPostProcessor 应用于给定的新 bean 实例。 bean 将已填充属性值。返回的 bean 实例可能是 // 原始的包装器。默认实现按原样返回给定的 bean
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
// 在任何 bean 初始化回调(如 InitializingBean 的 afterPropertiesSet 或自定义 init 方法)之 // 后,将此 BeanPostProcessor 应用于给定的新 bean 实例。 bean 将已填充属性值。返回的 bean 实例可 /// 能是原始的包装器。默认实现按原样返回给定的 bean
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
自定义BeanPostProcessor
自定义一个 BeanPostProcessor 实现,该实现调用每个 bean 的 toString() 方法打印内容输出到控制台。
类定义如下
/**
* @author zfd
* @version v1.0
* @date 2022/1/20 11:21
* @关于我 请关注公众号 螃蟹的Java笔记 获取更多技术系列
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 返回原始bean
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println( bean + " 名称是: " + beanName);
return bean;
}
}
@Component("xxxBeanOne")
public class BeanOne {
}
@Configuration
@ComponentScan
public class AppConfig {
}
测试程序及结果
@org.junit.Test
public void test1() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
BeanOne bean = context.getBean(BeanOne.class);
System.out.println(bean);
context.close();
}
// 结果
com.crab.spring.ioc.demo12.AppConfig$$EnhancerBySpringCGLIB$$da23c216@4445629 名称是: appConfig
com.crab.spring.ioc.demo12.BeanOne@45b9a632 名称是: xxxBeanOne
com.crab.spring.ioc.demo12.BeanOne@45b9a632
从结果看,MyBeanPostProcessor#postProcessAfterInitialization 输出了容器内初始化bean的名称。
使用 @Order 控制 BeanPostProcessor 执行顺序
实际程序程序中肯定存在多个 BeanPostProcessor 通过 @Order 来指定顺序。
增加 MyBeanPostProcessor2 指定顺序是 -2
@Component
@Order(-2)
public class MyBeanPostProcessor2 implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 返回原始bean
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor2 输出:" + bean + " 名称是: " + beanName);
return bean;
}
}
同样的测试程序,观察下结果
com.crab.spring.ioc.demo12.AppConfig$$EnhancerBySpringCGLIB$$6fb51f6@54c562f7 名称是: appConfig
MyBeanPostProcessor2 输出:com.crab.spring.ioc.demo12.AppConfig$$EnhancerBySpringCGLIB$$6fb51f6@54c562f7 名称是: appConfig
com.crab.spring.ioc.demo12.BeanOne@318ba8c8 名称是