热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Spring扩展点BeanFactoryPostProcessor使用技巧

1、Spring扩展点BeanFactoryPostProcessor使用技巧方法voidpostProcessBeanFactory(ConfigurableListable

1、Spring 扩展点 BeanFactoryPostProcessor 使用技巧

方法

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

其中提供一个 ConfigurableListableBeanFactory 回调对象,里面提供了很多框架内部使用的方法,建议的话使用它的实现类去注册 Bean 的信息。

不建议使用里面的方法直接实例化对象,因为过早的创建对象会导致后续 Spring 一些对 Bean 修饰执行不到,生命周期不完整。


1.1、BeanDefinitionRegistryPostProcessor

BeanFactoryPostProcessor 的实现类。

调用位置

org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List)

方法

void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

一般来使用当前方法来注册 BeanDefinition。

void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;

第一个参数填的是 Bean 的名称,第二个就是 Bean 的信息。一般可以使用以下方式去获取 BeanDefinition。


1.1.1、ScannedGenericBeanDefinition

public class Test {  private static final PathMatchingResourcePatternResolver PATTERN_RESOLVER &#61; new PathMatchingResourcePatternResolver();  private static final CachingMetadataReaderFactory READER_FACTORY &#61; new CachingMetadataReaderFactory();  static final String DEFAULT_RESOURCE_PATTERN &#61; "**/*.class";  public static void main(String[] args) throws IOException { System.out.println(doScan("com.rookie.mybatis.study")); }  private static List doScan(String basePackage) throws IOException { basePackage &#61; ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX &#43; resolveBasePackage(basePackage) &#43; &#39;/&#39; &#43; DEFAULT_RESOURCE_PATTERN; List result &#61; new ArrayList<>();// 当前会扫描该类下所有的类文件 Resource[] resources &#61; PATTERN_RESOLVER.getResources(basePackage); for (Resource resource : resources) { MetadataReader metadataReader &#61; READER_FACTORY.getMetadataReader(resource); ScannedGenericBeanDefinition sbd &#61; new ScannedGenericBeanDefinition(metadataReader); sbd.setSource(resource); result.add(sbd); } return result; }  private static String resolveBasePackage(String basePackage) { return ClassUtils.convertClassNameToResourcePath(new StandardEnvironment().resolveRequiredPlaceholders(basePackage)); }}

以上方式会将包下的所有类都扫描到然后添加到 Spring 容器当中&#xff0c;以上代码参考于 Mybatis 注册 Bean 的方式。


1.1.2、AnnotatedGenericBeanDefinition

这种方式就很直接了。直接 new 一个对象将需要的 Bean 的 class 放进去。

AnnotatedGenericBeanDefinition abd &#61; new AnnotatedGenericBeanDefinition(Test.class);

1.1.3、RootBeanDefinition

这个实现类和上面很类似&#xff0c;只不过多了几个构造方法&#xff1a;

RootBeanDefinition rootBeanDefinition &#61; new RootBeanDefinition(Test.class);

public RootBeanDefinition(String beanClassName);

最主要的还是以下的构造器&#xff1a;

public RootBeanDefinition(&#64;Nullable Class beanClass, &#64;Nullable ConstructorArgumentValues cargs,&#64;Nullable MutablePropertyValues pvs);

这个的话多了几个参数&#xff0c;ConstructorArgumentValues&#xff0c;看名字就大概可以猜的出是传构造参数的。当我们需要创建的 Bean 是有参构造器时&#xff0c;我们就可以使用当前方法将构造参数传递进去。

ConstructorArgumentValues constructorArgumentValues &#61; new ConstructorArgumentValues();// 添加构造参数 constructorArgumentValues.addGenericArgumentValue(111);

这个添加的顺序就代表了构造器参数的顺序。

第二个对象我们可以通过它去修改类属性的值。

// 修改类属性的值MutablePropertyValues mutablePropertyValues &#61; new MutablePropertyValues();mutablePropertyValues.addPropertyValue("age",555);

当然我们也可以通过其他工具类去创建&#xff1a;

BeanDefinitionBuilder beanDefinitionBuilder &#61; BeanDefinitionBuilder.rootBeanDefinition(TestBean.class);beanDefinitionBuilder.addConstructorArgValue(1);registry.registerBeanDefinition("testBean",beanDefinitionBuilder.getBeanDefinition());

1.2、环境变量 Environment

一般我们创建 Bean 的时候都喜欢去读 yml 的配置文件&#xff0c;但是在当前对象中&#xff0c;直接使用注入的方式是获取不到配置文件的&#xff1a;

&#64;Value("${test.case}")private String name; &#64;Autowiredprivate Environment environment;

这时候我们可以配合另外一个扩展点去获取环境变量。因为在当前扩展点执行的之后&#xff0c;Environment 是已经创建了放置进了 IOC 容器当中&#xff0c;我们需要通过下面的方式去获取&#xff1a;

&#64;Componentpublic class Test implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {  &#64;Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {  }  &#64;Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {  }  &#64;Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { Environment environment &#61; applicationContext.getEnvironment(); String xx &#61; environment.getProperty("xx"); }}

推荐阅读
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 本文讨论了在Spring 3.1中,数据源未能自动连接到@Configuration类的错误原因,并提供了解决方法。作者发现了错误的原因,并在代码中手动定义了PersistenceAnnotationBeanPostProcessor。作者删除了该定义后,问题得到解决。此外,作者还指出了默认的PersistenceAnnotationBeanPostProcessor的注册方式,并提供了自定义该bean定义的方法。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • java实现rstp格式转换使用ffmpeg实现linux命令第一步安装node.js和ffmpeg第二步搭建node.js启动websocket接收服务
    java实现rstp格式转换使用ffmpeg实现linux命令第一步安装node.js和ffmpeg第二步搭建node.js启动websocket接收服务第三步java实现 ... [详细]
  • JAVA调用存储过程CallableStatement对象的方法及使用示例
    本文介绍了使用JAVA调用存储过程CallableStatement对象的方法,包括创建CallableStatement对象、传入IN参数、注册OUT参数、传入INOUT参数、检索结果和OUT参数、处理NULL值等。通过示例代码演示了具体的调用过程。 ... [详细]
author-avatar
安小辰
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有