Bean实例化之前修改BeanDefinition示例详解
作者:刨红薯的小羊竿尔
BeanFactory
BeanFactory是Spring中容器功能的基础,用于存放所有已经加载的bean,为了保证程序上的高可扩展性,Spring针对BeanFactory做了大量的扩展。BeanFactoryPostProcessor是BeanFactory的后置处理器;比如在postProcessBeanFactory方法中,可以获取BeanDefinition的相关对象,并且修改该对象的属性。
@FunctionalInterface public interface BeanFactoryPostProcessor { void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException; }
通过BeanDefinition对象实例化Bean对象
Spring IOC在实例化Bean对象之前,需要先读取Bean的相关属性,保存到BeanDefinition
对象中,然后通过BeanDefinition对象,实例化Bean对象。如果我们需要修改BeanDefinition对象中的属性,就可以实现BeanFactoryPostProcessor接口,重写postProcessBeanFactory方法进行自定义,是不是很方便呢。
@Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory; BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class); beanDefinitionBuilder.addPropertyValue("id", 123456); beanDefinitionBuilder.addPropertyValue("label", "技术那些事儿"); defaultListableBeanFactory.registerBeanDefinition("user", beanDefinitionBuilder.getBeanDefinition()); } }
BeanFactoryPostProcessor使用目的:在BeanFactory标准初始化之后调用,用来定制和修改BeanFactory的内容;
BeanFactoryPostProcessor工作时机:所有的bean定义已经保存加载到beanFactory中,但bean的实例还没创建;
BeanFactoryPostProcessor和BeanPostProcessor类似,可以对beanDefinition进行处理,也就是说SpringIOC容器允许BeanFactoryPostProcessor在容器实际实例化任何bean之前读取beanDefinition,并有可能修改它。并且我们还可以配置自定义的BeanFactoryPostProcessor,如果想改变bean,那么使用beanPostProcessor。
并可以通过order属性来控制BeanFactoryPostProcessor的执行次序;因为只有实现了Ordered接口时,才可以设置这个属性,所以在实现BeanFactoryPostProcessor的时候,就应该考虑实现Ordered接口。
BeanFactoryPostProcessor的作用域是容器级的,只和你使用的容器有关,如果在一个容器中定义了一个BeanFactoryPostProcessor,它仅仅对此容器中的beanDefinition进行后处理。BeanFactoryPostProcessor不会对定义在另一个容器中的bean进行后处理,即便这两个容器都在同一个层次上。
BeanFactoryPostProcessor还有一个子接口BeanDefinitionRegistryPostProcessor,其内部添加了一个方法postProcessBeanDefinitionRegistry:
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
ConfigurationClassPostProcessor这个类非常重要,其实现了BeanDefinitionRegistryPostProcessor接口与PriorityOrdered接口:
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { int registryId = System.identityHashCode(registry); if (this.registriesPostProcessed.contains(registryId)) { throw new IllegalStateException( "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry); } if (this.factoriesPostProcessed.contains(registryId)) { throw new IllegalStateException( "postProcessBeanFactory already called on this post-processor against " + registry); } this.registriesPostProcessed.add(registryId); /** * @author lcy * 处理配置beanDefinition */ processConfigBeanDefinitions(registry); }
就是在这个方法里将配置类指定的类解析为BeanDefinition对象,并放入BeanFactory的beanDefinitionMap中。还有一点需要说明,这个类是在执行AnnotationConfigApplicationContext的无参构造方法时被解析为beanDefinition并放入map中的。在AnnotationConfigApplicationContext的refresh()内部的 invokeBeanFactoryPostProcessors(beanFactory)方法完成了对 BeanFactoryPostProcessor对象与BeanDefinitionRegistryPostProcessor对象相关方法的执行。
以上就是Bean实例化之前修改BeanDefinition示例详解的详细内容,更多关于Bean实例化修改BeanDefinition的资料请关注脚本之家其它相关文章!