javaee论坛

普通会员

225648

帖子

346

回复

360

积分

楼主
发表于 2019-11-18 08:49:10 | 查看: 194 | 回复: 1

专题系列分类:玩转SpringBoot2.x系列教程

1demo版本说明

开发工具:SpringToolSuite(STS)

springboot版本:2.0.5.RELEASE

jdk版本:1.8.0_144

在阅读该博客前建议大家一定要把demo写下来在自己的环境下,根据操作静下心来一步步看。阅读源码本身是一个比较费神的操作,建议大家一定要多看看明白后自己在把大体思路捋一下。 因为springboot用的也是spirng所以下面介绍主要是spirng而不是springboot特此说明。

2通过BeanPostProcessor进行Bean初始化回调前后进行自定义操作我们知道spring可以为我们创建bean对象实例和以及Bean 属性注入,但是如果我们想要在Bean自动装配完成后自定义操作怎么处理呢?我们需要BeanPostProcessor接口来完成自定义操作处理。当你还不知道我在说什么的情况下,那就直接看下面的代码吧。

定义一个名称为IMyBean的接口其中有2个方法一个获取自定义值getCustomValue一个进行设置自定义值的方法 setCustomValue

packagecn.lijunkui.customBean;publicinterfaceIMyBean{voidsetCustomValue(Stringv);StringgetCustomValue();}

创建名称为MyBean的实体类并实现IMyBean并通过@Component直接声明该类为spirng的bean 

packagecn.lijunkui.customBean;importorg.springframework.stereotype.Component;@ComponentpublicclassMyBeanimplementsIMyBean{privateStringcustomValue;@OverridepublicvoidsetCustomValue(StringcustomValue){this.customValue=customValue;}@OverridepublicStringgetCustomValue(){returncustomValue;}}

创建实现BeanPostProcessor的实现类完成对MyBean的初始化后自定义操作 如果在初始化MyBean后customValue的值如果为空则将其设置为“defaultValue” 

packagecn.lijunkui.customBean;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.BeansException;importorg.springframework.beans.factory.config.BeanPostProcessor;importorg.springframework.stereotype.Component;@ComponentpublicclassMyBeanPostProcessorimplementsBeanPostProcessor{privateLoggerlog=LoggerFactory.getLogger(MyBeanPostProcessor.class);@OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{returnbean;}@OverridepublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{if(beaninstanceofIMyBean){log.info("=======>postProcessAfterInitialization");IMyBeanmybean=(IMyBean)bean;if(mybean.getCustomValue()==null){mybean.setCustomValue("defaultValue");}}returnbean;}}

 通过在启动类中获取ConfigurableApplicationContext 获取MyBean测试customValue的值是否改变。(这里我们额外说一下Spirng中的bean都是通过BeanFactory进行管理的,在Spirng中默认使用的是DefaultListableBeanFactory也就是BeanFactory的实现。 而下面代码中ConfigurableApplicationContext getBean就是BeanFactory中的方法)

packagecn.lijunkui;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.context.ConfigurableApplicationContext;importcn.lijunkui.customBean.MyBean;@SpringBootApplicationpublicclassPrincipleApplication{privatestaticLoggerlog=LoggerFactory.getLogger(PrincipleApplication.class);publicstaticvoidmain(String[]args){ConfigurableApplicationContextrun=SpringApplication.run(PrincipleApplication.class,args);MyBeanmybean=run.getBean(MyBean.class);log.info("getCustomValue:"+mybean.getCustomValue());}}

测试结果:我们看到下图中加载的过程中进行了回调并且将customValue的值设置成了defaultValue 

为什么实现 BeanPostProcessor就可以进行bean初始化后的操作呢?想知道其中的原理我们就要去看看spring的源码了。

第一步在MyBeanPostProcessor postProcessAfterInitialization方法中打一个段断点然后启动spirngboot项目

当断点走到 postProcessAfterInitialization方法上事如下图它的调用链就出来了,是不是很清晰。

根据上图调用链我们继续查看 AbstractAutowireCapableBeanFactory.initializeBean方法该方法中我们看到和BeanPostProcessor有关的2个方法

applyBeanPostProcessorsBeforeInitialization 和applyBeanPostProcessorsBeforeInitialization  是不是感觉和BeanPostProcessor相关,下面是initializeBean具体逻辑实现

/***Initializethegivenbeaninstance,applyingfactorycallbacks*aswellasinitmethodsandbeanpostprocessors.*<p>Calledfrom{@link#createBean}fortraditionallydefinedbeans,*andfrom{@link#initializeBean}forexistingbeaninstances.*@parambeanNamethebeannameinthefactory(fordebuggingpurposes)*@parambeanthenewbeaninstancewemayneedtoinitialize*@parammbdthebeandefinitionthatthebeanwascreatedwith*(canalsobe{@codenull},ifgivenanexistingbeaninstance)*@returntheinitializedbeaninstance(potentiallywrapped)*@seeBeanNameAware*@seeBeanClassLoaderAware*@seeBeanFactoryAware*@see#applyBeanPostProcessorsBeforeInitialization*@see#invokeInitMethods*@see#applyBeanPostProcessorsAfterInitialization*/protectedObjectinitializeBean(finalStringbeanName,finalObjectbean,@NullableRootBeanDefinitionmbd){if(System.getSecurityManager()!=null){AccessController.doPrivileged((PrivilegedAction<Object>)()->{invokeAwareMethods(beanName,bean);returnnull;},getAccessControlContext());}else{invokeAwareMethods(beanName,bean);}ObjectwrappedBean=bean;if(mbd==null||!mbd.isSynthetic()){wrappedBean=applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);}try{invokeInitMethods(beanName,wrappedBean,mbd);}catch(Throwableex){thrownewBeanCreationException((mbd!=null?mbd.getResourceDescription():null),beanName,"Invocationofinitmethodfailed",ex);}if(mbd==null||!mbd.isSynthetic()){wrappedBean=applyBeanPostProcessorsAfterInitialization(wrappedBean,beanName);}returnwrappedBean;}

applyBeanPostProcessorsBeforeInitialization  方法的具体实现逻辑如下

@OverridepublicObjectapplyBeanPostProcessorsBeforeInitialization(ObjectexistingBean,StringbeanName)throwsBeansException{Objectresult=existingBean;for(BeanPostProcessorprocessor:getBeanPostProcessors()){Objectcurrent=processor.postProcessBeforeInitialization(result,beanName);if(current==null){returnresult;}result=current;}returnresult;}

当我们看到Objectcurrent=processor.postProcessBeforeInitialization(result,beanName);是不是知道了这里会获取所有的BeanPostProcessor 然后调用postProcessBeforeInitialization

BeanPostProcessors逻辑如下:

获取AbstractBeanFactory中的beanPostProcessors 

/***ReturnthelistofBeanPostProcessorsthatwillgetapplied*tobeanscreatedwiththisfactory.*/publicList<BeanPostProcessor>getBeanPostProcessors(){returnthis.beanPostProcessors;}

applyBeanPostProcessorsAfterInitialization 逻辑和applyBeanPostProcessorsBeforeInitialization逻辑基本一直代码如下

@OverridepublicObjectapplyBeanPostProcessorsAfterInitialization(ObjectexistingBean,StringbeanName)throwsBeansException{Objectresult=existingBean;for(BeanPostProcessorprocessor:getBeanPostProcessors()){Objectcurrent=processor.postProcessAfterInitialization(result,beanName);if(current==null){returnresult;}result=current;}returnresult;}

BeanPostProcessor调用时序图如下:中间很多流程做了简化画的是核心的逻辑。

还有一个问题就是我们的BeanPostProcessor集合是在什么时添加的?关闭到我们的springboot服务

还是下图的断点在次一debug方式启动

通过调用的链路往下找知道找到AbstractApplicationContext中的refresh()方法中的registerBeanPostProcessors(beanFactory) 

通过PostProcessorRegistrationDelegate.registerBeanPostProcessors将放入到beanFactory中

 registerBeanPostProcessors方法中获取到所有的BeanPostProcessor然后放入集合中

 然后再将BeanPostProcessor集合放入到beanFactory中

 PostProcessorRegistrationDelegateregisterBeanPostProcessors具体源码逻辑如下

publicstaticvoidregisterBeanPostProcessors(ConfigurableListableBeanFactorybeanFactory,AbstractApplicationContextapplicationContext){String[]postProcessorNames=beanFactory.getBeanNamesForType(BeanPostProcessor.class,true,false);//RegisterBeanPostProcessorCheckerthatlogsaninfomessagewhen//abeaniscreatedduringBeanPostProcessorinstantiation,i.e.when//abeanisnoteligibleforgettingprocessedbyallBeanPostProcessors.intbeanProcessorTargetCount=beanFactory.getBeanPostProcessorCount()+1+postProcessorNames.length;beanFactory.addBeanPostProcessor(newBeanPostProcessorChecker(beanFactory,beanProcessorTargetCount));//SeparatebetweenBeanPostProcessorsthatimplementPriorityOrdered,//Ordered,andtherest.List<BeanPostProcessor>priorityOrderedPostProcessors=newArrayList<>();List<BeanPostProcessor>internalPostProcessors=newArrayList<>();List<String>orderedPostProcessorNames=newArrayList<>();List<String>nonOrderedPostProcessorNames=newArrayList<>();for(StringppName:postProcessorNames){if(beanFactory.isTypeMatch(ppName,PriorityOrdered.class)){BeanPostProcessorpp=beanFactory.getBean(ppName,BeanPostProcessor.class);priorityOrderedPostProcessors.add(pp);if(ppinstanceofMergedBeanDefinitionPostProcessor){internalPostProcessors.add(pp);}}elseif(beanFactory.isTypeMatch(ppName,Ordered.class)){orderedPostProcessorNames.add(ppName);}else{nonOrderedPostProcessorNames.add(ppName);}}//First,registertheBeanPostProcessorsthatimplementPriorityOrdered.sortPostProcessors(priorityOrderedPostProcessors,beanFactory);registerBeanPostProcessors(beanFactory,priorityOrderedPostProcessors);//Next,registertheBeanPostProcessorsthatimplementOrdered.List<BeanPostProcessor>orderedPostProcessors=newArrayList<>();for(StringppName:orderedPostProcessorNames){BeanPostProcessorpp=beanFactory.getBean(ppName,BeanPostProcessor.class);orderedPostProcessors.add(pp);if(ppinstanceofMergedBeanDefinitionPostProcessor){internalPostProcessors.add(pp);}}sortPostProcessors(orderedPostProcessors,beanFactory);registerBeanPostProcessors(beanFactory,orderedPostProcessors);//Now,registerallregularBeanPostProcessors.List<BeanPostProcessor>nonOrderedPostProcessors=newArrayList<>();for(StringppName:nonOrderedPostProcessorNames){BeanPostProcessorpp=beanFactory.getBean(ppName,BeanPostProcessor.class);nonOrderedPostProcessors.add(pp);if(ppinstanceofMergedBeanDefinitionPostProcessor){internalPostProcessors.add(pp);}}registerBeanPostProcessors(beanFactory,nonOrderedPostProcessors);//Finally,re-registerallinternalBeanPostProcessors.sortPostProcessors(internalPostProcessors,beanFactory);registerBeanPostProcessors(beanFactory,internalPostProcessors);//Re-registerpost-processorfordetectinginnerbeansasApplicationListeners,//movingittotheendoftheprocessorchain(forpickingupproxiesetc).beanFactory.addBeanPostProcessor(newApplicationListenerDetector(applicationContext));}privatestaticvoidregisterBeanPostProcessors(ConfigurableListableBeanFactorybeanFactory,List<BeanPostProcessor>postProcessors){for(BeanPostProcessorpostProcessor:postProcessors){beanFactory.addBeanPostProcessor(postProcessor);}}

通过下图了解springboot启动后如何执行到 AbstractApplicationContext  refresh方法流程。

 

大致流程如下: 

在Spring初始化完成后会回调GenericApplicationContext中的refresh方法,然后再通过AbstractApplicationContext 抽象类中的 refresh来实现。

在refresh方法中registerBeanPostProcessors调用了PostProcessorRegistrationDelegate,将BeanFactory作为参数传入,在registerBeanPostProcessors中获取所有的BeanPostProcessor获取完所有实现类后,根据实现类上的顺序进行排序,然后将排序好的集合对象调用BeanFactory.addBeanPostProcessor注册到BeanFactory中。

这样在AbstractAutowireCapableBeanFactory中就可以从它的父类AbstractBeanFactory中直接获取到BeanPostProcessor集合对象了,也就是上面调用的getBeanPostProcessors()方法。

 


普通会员

0

帖子

337

回复

341

积分
沙发
发表于 2022-12-28 11:55:24

谢谢楼主分享

您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017