BeanFactoryPostProcessor 向容器添加自定义bean
在之前的一篇文章中写到通过BeanFactoryPostProcessor向Spring容器中添加自定义bean,最近在学习Spring源码过程中发现一个更强大更严谨的方式–BeanDefinitionRegistryPostProcessor,这是一个继承了BeanFactoryPostProcessor的接口,该接口增加了如下方法
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
作者的注释也说了这个方法允许在下一个后置处理阶段之前添加更多的bean definitions,所以通过实现此接口向Spring容器添加自定义bean更合适。
实现此接口可以拿到容器中的BeanDefinitionRegistry,它提供了如上图所示的几个API,可以根据beanName判断容器中是否存在该bean definition,如果不存在再调用registerBeanDefinition()将bean定义注册到容器,存在就视情况removeBeanDefinition()或者放弃注册等,这样更加严谨一些。而BeanFactoryPostProcessor的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)用来处理spring已经扫描进来的bean definitions更合适。
ImportBeanDefinitionRegistrar
追加另外一个往容器添加bean的方法,通过实现ImportBeanDefinitionRegistrar接口,在配置类通过@Import引入,Mybatis的@MapperScan就是利用这种方式,其MapperScannerRegistrar就实现了ImportBeanDefinitionRegistrar接口,使用ClassPathBeanDefinitionScanner扫描basePackages下的类并创建bean definitions放到容器里。(这里的说法需要更严谨一些,因为要扫描mapper都是接口,Mybatis通过MapperFactoryBean,它实现了FactoryBean接口,FactoryBean会返回两个对象,一个是它自己,另一个是getObject()返回的代理对象,Mybatis应该就是利用了getObject()通过接口来生成代理对象,这里有时间再研究一些)。