Bean实例化之前修改BeanDefinition示例详解

作者:刨红薯的小羊竿尔 时间:2023-10-26 23:31:09 

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对象相关方法的执行。

来源:https://juejin.cn/post/7179241069651951653

标签:Bean,实例化,BeanDefinition
0
投稿

猜你喜欢

  • Android中检查、监听电量和充电状态的方法

    2023-05-15 23:23:19
  • 一文带你探究Spring中Bean的线程安全性问题

    2023-10-03 10:52:13
  • 使用java打印心型、圆形图案的实现代码

    2021-08-30 19:50:45
  • java poi解析word的方法

    2023-08-28 07:31:28
  • SpringBoot 自定义+动态切换数据源教程

    2021-10-13 21:30:39
  • Java设计模式之模板方法模式Template Method Pattern详解

    2023-09-21 12:28:04
  • android实现可自由移动、监听点击事件的悬浮窗

    2022-04-12 14:15:31
  • C#中LINQ多条件JOIN时为什么可以使用匿名类

    2023-01-24 15:38:21
  • Android自定义ScrollView实现阻尼回弹

    2021-11-23 07:20:19
  • Android接入阿里云热修复介绍

    2023-09-16 08:53:01
  • Java使用Iterator迭代器遍历集合数据的方法小结

    2021-10-28 00:22:40
  • Springboot Vue实现单点登陆功能示例详解

    2023-11-05 00:29:11
  • Android 中Banner的使用详解

    2023-08-18 08:57:02
  • 解析C#多线程编程中异步多线程的实现及线程池的使用

    2021-10-23 02:36:23
  • Java中的SuppressWarnings注解使用

    2023-08-18 17:31:19
  • 简单了解JAVA public class与class区别

    2023-11-15 23:59:26
  • Java利用自定义注解实现数据校验

    2022-12-03 09:56:49
  • 5分钟快速学会spring boot整合JdbcTemplate的方法

    2022-04-01 15:56:11
  • 图文详解Java中的字节输入与输出流

    2022-12-23 23:14:48
  • C#实现滑动开关效果

    2023-11-26 22:18:29
  • asp之家 软件编程 m.aspxhome.com