您的位置 首页 > 德语词汇

processor是什么意思?用法、例句?Spring扩展点:后置处理器PostProcessor

大家好,关于processor是什么意思?用法、例句很多朋友都还不太明白,今天小编就来为大家分享关于Spring扩展点:后置处理器PostProcessor的知识,希望对各位有所帮助!

之前我们对Spring相关注解进行全方面的解析与总结,在此期间反复提到了一个核心配置解析类:ConfigurationClassPostProcessor,我们称之为配置类后置处理器。什么是后置处理器呢?其实后置处理器是**Spring提供给我们的一个非常重要的扩展点**,并且Spring内部的很多功能也是通过后置处理器来完成的,ConfigurationClassPostProcessor的重要性就说明这一点,同时该扩展点也方便Spring与其他框架进行集成,如Spring集成mybatis框架,就是通过后置处理器MapperScannerConfigurer实现了扫描mapper接口注入到Spring容器中的。

processor是什么意思?用法、例句?Spring扩展点:后置处理器PostProcessor

Spring框架中大致提供了以下三个核心后置处理器:BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor,BeanPostProcessor,其他的后置处理器都是继承自这三个。三个扩展点的主要功能作用如下:

根据上面各个处理器的功能作用描述可以得到三个处理器的执行顺序:

BeanDefinitionRegistryPostProcessor→BeanFactoryPostProcessor→BeanPostProcessor\n复制代码

这也是Spring的bean生命周期流程的部分体现,这三个后置处理器调用时机都在bean的生命周期中,当然bean的生命周期也是一个重要知识点,且生命周期远不止这几个扩展点,后续会安排分析一波。

项目推荐:基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba企业级系统架构底层框架封装,解决业务开发时常见的非功能性需求,防止重复造轮子,方便业务快速开发和企业技术栈框架统一管理。引入组件化的思想实现高内聚低耦合并且高度可配置化,做到可插拔。严格控制包依赖和统一版本管理,做到最少化依赖。注重代码规范和注释,非常适合个人学习和企业使用

Github地址:github.com/plasticene/…

Gitee地址:gitee.com/plasticene3…

微信公众号Shepherd进阶笔记

接下来我们就分别分析下这三个后置处理器:

publicinterfaceBeanDefinitionRegistryPostProcessorextendsBeanFactoryPostProcessor{\n\n/**\n*Modifytheapplicationcontext'sinternalbeandefinitionregistryafterits\n*standardinitialization.Allregularbeandefinitionswillhavebeenloaded,\n*butnobeanswillhavebeeninstantiatedyet.Thisallowsforaddingfurther\n*beandefinitionsbeforethenextpost-processingphasekicksin.\n*@paramregistrythebeandefinitionregistryusedbytheapplicationcontext\n*@throwsorg.springframework.beans.BeansExceptionincaseoferrors\n*/\nvoidpostProcessBeanDefinitionRegistry(BeanDefinitionRegistryregistry)throwsBeansException;\n?\n}\n复制代码

可以看到BeanDefinitionRegistryPostProcessor继承自上面的BeanFactoryPostProcessor,说明BeanDefinitionRegistryPostProcessor对BeanFactoryPostProcessor提供的方法进行了增强扩展,实现BeanDefinitionRegistryPostProcessor就必须实现两个接口定义的方法。从上面代码注释翻译来看:BeanDefinitionRegistryPostProcessor主要完成所有常规beanDefinition已经加载完毕,然后可以再添加一些额外的beanDefinition,一句话总结其功能作用就是注册beanDefinition的,ConfigurationClassPostProcessor就是实现BeanDefinitionRegistryPostProcessor来完成配置类及其相关注解解析得到beanDefinition注册到Spring上下文中的。

@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublicclassBoo{\nprivateLongid;\nprivateStringname;\n}\n复制代码

然后自定义个BeanDefinitionRegistryPostProcessor:

@Component\n//需要把该后置处理器注入Spring容器中\npublicclassMyBeanDefinitionRegistryPostProcessorimplementsBeanDefinitionRegistryPostProcessor{\n@Override\npublicvoidpostProcessBeanDefinitionRegistry(BeanDefinitionRegistryregistry)throwsBeansException{\n//注入boo\nBeanDefinitionbeanDefinition=newRootBeanDefinition();\nbeanDefinition.setBeanClassName("com.shepherd.common.bean.Boo");\nregistry.registerBeanDefinition("boo",beanDefinition);\n}\n?\n@Override\npublicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throwsBeansException{\n//该方法是BeanFactoryPostProcessor的方法,这里就不做任何逻辑处理,后面会单独演示\n?\n}\n}\n复制代码

执行测试方法:

@ComponentScan(basePackages={"com.shepherd.common.config"})\n@Configuration\npublicclassMyConfig{\n?\npublicstaticvoidmain(String[]args){\nAnnotationConfigApplicationContextapplicationContext=newAnnotationConfigApplicationContext(MyConfig.class);\nString[]beanDefinitionNames=applicationContext.getBeanDefinitionNames();\n//遍历Spring容器中的beanName\nfor(StringbeanDefinitionName:beanDefinitionNames){\nSystem.out.println(beanDefinitionName);\n}\n}\n}\n复制代码

会发现结果打印中有boo,说明上面后置处理器成功添加beanDefinition,Spring后续进行了bean的注入。

其实核心配置解析类后置处理器ConfigurationClassPostProcessor就是最好的示例,不熟悉的可以跳转到之前总结的@Import的使用和实现原理,看看ConfigurationClassPostProcessor这个后置处理器是怎么实现对@Import的解析的

@FunctionalInterface\npublicinterfaceBeanFactoryPostProcessor{\n?\n/**\n*Modifytheapplicationcontext'sinternalbeanfactoryafteritsstandard\n*initialization.Allbeandefinitionswillhavebeenloaded,butnobeans\n*willhavebeeninstantiatedyet.Thisallowsforoverridingoradding\n*propertieseventoeager-initializingbeans.\n*@parambeanFactorythebeanfactoryusedbytheapplicationcontext\n*@throwsorg.springframework.beans.BeansExceptionincaseoferrors\n*/\nvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throwsBeansException;\n?\n}\n复制代码

@FunctionalInterface注解表示它是一个函数式接口,可以使用Lambda表达式调用,当然这不是重点,重点看注释,这里我是特意把源码的注释copy出来的,翻译过来大概意思就是:所有的beanDefinition已经全部加载完毕,然后该后置处理器可以对这些beanDefinition做一些属性的修改操作。这就是对BeanFactoryPostProcessor作用功能的描述

我们在2.1小节的案例基础中自定义一个BeanFactoryPostProcessor:

@Component\npublicclassMyBeanFactoryPostProcessorimplementsBeanFactoryPostProcessor{\n@Override\npublicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throwsBeansException{\nSystem.out.println("BeanFactoryPostProcessorexecute...");\nBeanDefinitionbeanDefinition=beanFactory.getBeanDefinition("boo");\nif(Objects.nonNull(beanDefinition)){\nbeanDefinition.setDescription("芽儿哟,可以的");\n}\n}\n}\n复制代码

这里就是对上面添加名为boo的beanDefinition进行了属性修改。

@ComponentScan(basePackages={"com.shepherd.common.config"})\n@Configuration\npublicclassMyConfig{\n?\npublicstaticvoidmain(String[]args){\nAnnotationConfigApplicationContextapplicationContext=newAnnotationConfigApplicationContext(MyConfig.class);\nBeanDefinitionbeanDefinition=applicationContext.getBeanDefinition("boo");\nSystem.out.println(beanDefinition.getDescription());\n}\n}\n?\n复制代码

执行结果控制台打印:

芽儿哟,可以的\n复制代码

由此可见,MyBeanFactoryPostProcessor后置处理器成功修改了boo的属性。当然BeanFactoryPostProcessor也可以注册beanDefinition的,看你怎么用。

publicinterfaceBeanPostProcessor{\n?\n/**\n*Applythis{@codeBeanPostProcessor}tothegivennewbeaninstance<i>before</i>anybean\n*initializationcallbacks(likeInitializingBean's{@codeafterPropertiesSet}\n*oracustominit-method).Thebeanwillalreadybepopulatedwithpropertyvalues.\n*Thereturnedbeaninstancemaybeawrapperaroundtheoriginal.\n*<p>Thedefaultimplementationreturnsthegiven{@codebean}as-is.\n*@parambeanthenewbeaninstance\n*@parambeanNamethenameofthebean\n*@returnthebeaninstancetouse,eithertheoriginalorawrappedone;\n*if{@codenull},nosubsequentBeanPostProcessorswillbeinvoked\n*@throwsorg.springframework.beans.BeansExceptionincaseoferrors\n*@seeorg.springframework.beans.factory.InitializingBean#afterPropertiesSet\n\n*在属性注入完毕,init初始化方法执行之前被回调\n*/\n@Nullable\ndefaultObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{\nreturnbean;\n}\n?\n/**\n*Applythis{@codeBeanPostProcessor}tothegivennewbeaninstance<i>after</i>anybean\n*initializationcallbacks(likeInitializingBean's{@codeafterPropertiesSet}\n*oracustominit-method).Thebeanwillalreadybepopulatedwithpropertyvalues.\n*Thereturnedbeaninstancemaybeawrapperaroundtheoriginal.\n*<p>IncaseofaFactoryBean,thiscallbackwillbeinvokedforboththeFactoryBean\n*instanceandtheobjectscreatedbytheFactoryBean(asofSpring2.0).The\n*post-processorcandecidewhethertoapplytoeithertheFactoryBeanorcreated\n*objectsorboththroughcorresponding{@codebeaninstanceofFactoryBean}checks.\n*<p>Thiscallbackwillalsobeinvokedafterashort-circuitingtriggeredbya\n*{@linkInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation}method,\n*incontrasttoallother{@codeBeanPostProcessor}callbacks.\n*<p>Thedefaultimplementationreturnsthegiven{@codebean}as-is.\n*@parambeanthenewbeaninstance\n*@parambeanNamethenameofthebean\n*@returnthebeaninstancetouse,eithertheoriginalorawrappedone;\n*if{@codenull},nosubsequentBeanPostProcessorswillbeinvoked\n*@throwsorg.springframework.beans.BeansExceptionincaseoferrors\n*@seeorg.springframework.beans.factory.InitializingBean#afterPropertiesSet\n*@seeorg.springframework.beans.factory.FactoryBean\n\n*在初始化方法执行之后,被添加到单例池singletonObjects之前被回调\n*/\n@Nullable\ndefaultObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{\nreturnbean;\n}\n?\n}\n复制代码

Bean被实例化后,到最终缓存到名为singletonObjects单例池之前,中间会经过Bean的初始化过程,例如:属性的填充、初始方法init的执行等,BeanPostProcessor就是这一阶段的对外扩展点,我们称之为Bean后置处理器。跟上面的Bean工厂后处理器相似,它也是一个接口,实现了该接口并被容器管理的BeanPostProcessor,会在流程节点上被Spring自动调用。

先改造一下上面的bean定义,提供一个实例化构造方法和初始化方法:

@Data\n@AllArgsConstructor\npublicclassBoo{\nprivateLongid;\nprivateStringname;\n?\npublicBoo(){\nSystem.out.println("boo实例化构造方法执行了...");\n}\n?\n@PostConstruct\n//该注解表示实例化之后执行该初始化方法\npublicvoidinit(){\nSystem.out.println("boo执行初始化init()方法了...");\n}\n}\n?\n复制代码

然后自定义一个beanPostProcessor:

@Component\npublicclassMyBeanPostProcessorimplementsBeanPostProcessor{\n@Override\npublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{\nSystem.out.println("beanPostProcessor的before()执行了...."+beanName);\nreturnbean;\n}\n?\n@Override\npublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{\nSystem.out.println("beanPostProcessor的after()执行了...."+beanName);\nreturnbean;\n}\n}\n复制代码

测试方法:

@ComponentScan(basePackages={"com.shepherd.common.config"})\n@Configuration\npublicclassMyConfig{\n?\n\npublicstaticvoidmain(String[]args){\nAnnotationConfigApplicationContextapplicationContext=newAnnotationConfigApplicationContext(MyConfig.class);\n\n}\n?\n复制代码

打印结果如下:

boo实例化构造方法执行了...\nbeanPostProcessor的before()执行了....boo\nboo执行初始化init()方法了...\nbeanPostProcessor的after()执行了....boo\n复制代码

这严格说明BeanPostProcessor方法的执行时间点和顺序,BeanPostProcessor是在bean实例化之后,对bean的初始化init()方法前后进行回调扩展的,这时候你可能会想如果要对bean的实例化前后进行扩展怎么办?Spring肯定也想到这一点,提供了继承自BeanPostProcessor的扩展类后置处理器:

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor该接口继承了BeanPostProcess接口,区别如下:

BeanPostProcess接口只在bean的初始化阶段进行扩展,而InstantiationAwareBeanPostProcessor接口在此基础上增加了3个方法,把可扩展的范围增加了实例化阶段和属性注入阶段。

该类主要的扩展点有以下5个方法,主要在bean生命周期的两大阶段:实例化阶段初始化阶段,下面一起进行说明,按调用顺序为:

使用场景:这个扩展点非常有用,无论是写中间件和业务中,都能利用这个特性。比如对实现了某一类接口的bean在各个生命期间进行收集,或者对某个类型的bean进行统一的设值等等。

SmartInstantiationAwareBeanPostProcessor

该扩展接口集成自上面的InstantiationAwareBeanPostProcessor,有3个触发点方法:

Spring注解开发和SpringBoot自动装配是当下主流开发首选,我们一再强调其快捷。高效性。现在在开发中间件和公共依赖工具的时候也会用到自动装配特性。让使用者以最小的代价接入。想要深入掌握自动装配套路,就必须要了解Spring对于bean的构造生命周期以及各个扩展接口,如之前我们总结的Spring基于相关注解开发,其背后核心原理就是通过ConfigurationClassPostProcessor这个后置处理器实现的,也就是说Spring通过自己提供的后置处理器扩展点实现了注解解析功能,且在别的地方也有大量应用,可见后置处理器这个扩展点的重要性不言而喻啦。

好了,本文到此结束,如果可以帮助到大家,还望关注本站哦!

本站涵盖的内容、图片、视频等数据,部分未能与原作者取得联系。若涉及版权问题,请及时通知我们并提供相关证明材料,我们将及时予以删除!谢谢大家的理解与支持!

Copyright © 2023