1、BeanFactoryPostProcessor
BeanFactoryPostProcessor 是一个接口,执行时机是当 beanDefinition 放入到 beanDefinitionMap 之后会回调这个接口中的 postProcessBeanFactory 方法
从这个执行时机,我们可以看出,既然是 beanDefinition 放入到 beanDefinitionMap 之后 会回调 postProcessBeanFactory 方法,那么我们就由机会修改 BeanDefinition 了,一旦修改 BeanDefinition 那么返回的对象就会发生改变
下面这个案例本来我们期望的是拿到 beanService,结果我们修改了 BeanDefinition,替换了 BeanClass 为 TestBean.class,所以我们在获取 beanService 的时候,就会得到 testBean 对象
@Component // 交给 Spring 容器管理
public class BeanService {
}
// 并没有交给 Spring 容器管理,只是一个 POJO
public class TestService {
}
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
/*
在 put 完 beanDefinitionMap 之后,调用 postProcessBeanFactory
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition beanDefinition =
(GenericBeanDefinition) beanFactory.getBeanDefinition("beanService");
beanDefinition.setBeanClass(TestBean.class);
}
}
验证结果如下:
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.register(AppConfig.class);
ac.refresh();
System.out.println(ac.getBean("beanService")); // TestBean@79be0360
System.out.println(ac.getBean(TestBean.class)); // TestBean@79be0360
}
}
2、BeanDefinitionRegistryPostProcessor
Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for the registration of further bean definitions before regular BeanFactoryPostProcessor detection kicks in. In particular, BeanDefinitionRegistryPostProcessor may register further bean definitions which in turn define BeanFactoryPostProcessor instances.
BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor,其实他也是一个 bean 工厂的后置处理器(也就是他实现了两个接口,在不同时机调用不同的接口)
BeanDefinitionRegistryPostProcessor 执行的时机比 BeanFactoryPostProcessor 要靠前
BeanDefinitionRegistryPostProcessor 本身有一个接口方法是
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry);
这个方法可以完成 bean 的动态扫描,我们也可以扩展这个类,完成自己的动态扫描逻辑(如 MyBatis 的 MapperScanner 就是扩展了这个类)
Spring 中它有一个实现类是 ConfigurationClassPostProcessor,这个类的作用是解析配置类,并完成动态扫描
3、自定义注解
所谓的自定义注解,就是让 Spring 认识我们自己写的注解,如何让 Spring 认识呢?关键就是让 Spring 把我们自定义的注解也进行扫描,那么扫描的关键就是可以加入到 Spring 的候选对象集合中,核心就是 this.includeFilters 这个过滤器
详情参考[《@ComponentScan 详解》**](https://www.yuque.com/nashihuakai/gg5mus/oi6bkz)
@MyComponent
public class CustomTestBean {
}
@MyComponent
public class CustomBean {
public CustomBean(CustomTestBean customTestBean) {
System.out.println(customTestBean);
}
}
ClassPathBeanDefinitionScanner customScanner = new ClassPathBeanDefinitionScanner(ac);
customScanner.addIncludeFilter(new AnnotationTypeFilter(MyComponent.class));
int scan = customScanner.scan("org.wesoft.spring.scan");
System.out.println(scan); // 扫描到符合要求 bean 的数量
4、InstantiationAwareBeanPostProcessor
提供是否继续完成属性注入,如果我们希望 Spring 不要自动完成属性注入,那么我们可以重写 postProcessAfterInstantiation 方法,让它返回 false,则 Spirng 会停止所有的属性注入
boolean continueWithPropertyPopulation = true;
// ★ 提供一个扩展点
// 如果程序员提供一个类,实现了 InstantiationAwareBeanPostProcessor,
// 并重写 postProcessAfterInstantiation 并返回 false,就不会完成属性注入
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 调用 postProcessAfterInstantiation 方法,判断是否进行属性填充
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
// 只要有一个后置处理器返回 false,就不会进行属性填充
continueWithPropertyPopulation = false;
break;
}
}
}
}