BeanFactoryPostProcessor
是一个函数式接口,里面只有一个方法:java
@FunctionalInterface public interface BeanFactoryPostProcessor { void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException; }
再看一下doc文档上的相关描述:编程
Allows for custom modification of an application context's bean definitions, adapting the bean property values of the context's underlying bean factory. Application contexts can auto-detect BeanFactoryPostProcessor beans in their bean definitions and apply them before any other beans get created. A BeanFactoryPostProcessor may interact with and modify bean definitions, but never bean instances. Doing so may cause premature bean instantiation, violating the container and causing unintended side-effects. If bean instance interaction is required, consider implementing BeanPostProcessor instead.app
机器翻译:容许自定义修改应用程序上下文的bean定义,调整上下文的基础bean工厂的bean属性值。应用程序上下文能够在其bean定义中自动检测BeanFactoryPostProcessor bean,并在建立任何其余bean以前先建立BeanFactoryPostProcessor。BeanFactoryPostProcessor能够与bean定义交互并修改bean定义,但毫不能与bean实例交互。这样作可能会致使bean过早实例化,违反容器并致使意外的反作用。若是须要bean实例交互,请考虑实现BeanPostProcessor。实现该接口,能够容许咱们的程序获取到BeanFactory
,从而修改BeanFactory
,能够实现编程式的往Spring容器中添加Bean。
总结,也就是说,咱们能够经过实现BeanFactoryPostProcessor
接口,获取BeanFactory
,操做BeanFactory
对象,修改BeanDefinition
,但不要去实例化bean。ide
BeanDefinitionRegistryPostProcessor
是BeanFactoryPostProcessor
的子类,在父类的基础上,增长了新的方法,容许咱们获取到BeanDefinitionRegistry
,从而编码动态修改BeanDefinition
。例如往BeanDefinition
中添加一个新的BeanDefinition
。函数
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor { void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException; }
Extension to the standard 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.post
机器翻译:对标准BeanFactoryPostProcessor SPI的扩展,容许在进行常规BeanFactoryPostProcessor检测以前注册其余Bean定义。特别是,BeanDefinitionRegistryPostProcessor能够注册其余Bean定义,这些定义又定义了BeanFactoryPostProcessor实例。
那么BeanFactoryPostProcessor
和BeanDefinitionRegistryPostProcessor
接口是在何时被回调的呢?ui
看过我以前文章的小伙伴不知道还记不得的,这两个接口是在AbstractApplicationContext#refresh
方法中执行到invokeBeanFactoryPostProcessors(beanFactory);
方法时被执行的。Spring的编码取名真的很艺术,方法名虽然很长,可是一看就知道在作什么。this
@Repository public class OrderDao { public void query() { System.out.println("OrderDao query..."); } } public class OrderService { private OrderDao orderDao; public void setDao(OrderDao orderDao) { this.orderDao = orderDao; } public void init() { System.out.println("OrderService init..."); } public void query() { orderDao.query(); } } @Component public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { //向Spring容器中注册OrderService BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(OrderService.class) //这里的属性名是根据setter方法 .addPropertyReference("dao", "orderDao") .setInitMethodName("init") .setScope(BeanDefinition.SCOPE_SINGLETON) .getBeanDefinition(); registry.registerBeanDefinition("orderService", beanDefinition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // 在这里修改orderService bean的scope为PROTOTYPE BeanDefinition beanDefinition = beanFactory.getBeanDefinition("orderService"); beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE); } }
OrderService
经过MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
注册到了容器中,又经过MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory
方法修改了其Scope。最后运行主方法:编码
@Configuration @ComponentScan public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class); //能成功从容器中获取orderService,并成功调用orderService.query();方法 OrderService orderService = context.getBean(OrderService.class); orderService.query(); OrderService orderService2 = context.getBean(OrderService.class); //false,orderService已经不是单例 System.out.println(orderService == orderService2); context.close(); } }
在Spring中ConfigurationClassPostProcessor
同时实现了BeanDefinitionRegistryPostProcessor
接口和其父类接口中的方法。spa
ConfigurationClassPostProcessor#postProcessBeanFactory
:主要负责对Full Configuration 配置进行加强,拦截@Bean
方法来确保加强执行@Bean
方法的语义。ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
:负责扫描咱们的程序,根据程序的中Bean建立BeanDefinition
,并注册到容器中。欢迎各位关注公众号: