今天自由互联小编给大家分享一下Spring中@Configuration注解修改的类生成代理的原因是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方 今天自由互联小编给大家分
今天自由互联小编给大家分享一下Spring中@Configuration注解修改的类生成代理的原因是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
前言
在Spring中只要被@Configuration注解修饰的类,Spring就会为其生成代理对象,至于这样做的主要原因就是为了解决生成对象的单例问题。
说明
实际上作者在ConfigurationClassEnhancer这个类也有注解说明
场景
如果Spring不做处理,下面输出的一定的是false,但是实际上输出的结果是true,那么只有可能是代理类做了特殊处理。
@ConfigurationpublicclassMyConfiguration{@BeanpublicTestAa(){returnnewTestA();}@BeanpublicTestBb(){TestAa=a();TestAb=a();System.out.println(a==b);returnnewTestB();}}处理分析
生成的代理对象,最终会调用ConfigurationClassEnhancer内部类BeanMethodInterceptor的intercept方法,如果不是当前调用的Bean对象(也就是isCurrentlyInvokedFactoryMethod(beanMethod)返回false),则会调用resolveBeanReference方法。
publicObjectintercept(ObjectenhancedConfigInstance,MethodbeanMethod,Object[]beanMethodArgs,MethodProxycglibMethodProxy)throwsThrowable{ConfigurableBeanFactorybeanFactory=getBeanFactory(enhancedConfigInstance);StringbeanName=BeanAnnotationHelper.determineBeanNameFor(beanMethod);//Determinewhetherthisbeanisascoped-proxyif(BeanAnnotationHelper.isScopedProxy(beanMethod)){StringscopedBeanName=ScopedProxyCreator.getTargetBeanName(beanName);if(beanFactory.isCurrentlyInCreation(scopedBeanName)){beanName=scopedBeanName;}}//Tohandlethecaseofaninter-beanmethodreference,wemustexplicitlycheckthe//containerforalreadycachedinstances.//First,checktoseeiftherequestedbeanisaFactoryBean.Ifso,createasubclass//proxythatinterceptscallstogetObject()andreturnsanycachedbeaninstance.//ThisensuresthatthesemanticsofcallingaFactoryBeanfromwithin@Beanmethods//isthesameasthatofreferringtoaFactoryBeanwithinXML.SeeSPR-6602.if(factoryContainsBean(beanFactory,BeanFactory.FACTORY_BEAN_PREFIX+beanName)if(factoryBeaninstanceofScopedProxyFactoryBean){//Scopedproxyfactorybeansareaspecialcaseandshouldnotbefurtherproxied}else{//ItisacandidateFactoryBean-goaheadwithenhancementreturnenhanceFactoryBean(factoryBean,beanMethod.getReturnType(),beanFactory,beanName);}}if(isCurrentlyInvokedFactoryMethod(beanMethod)){//Thefactoryiscallingthebeanmethodinordertoinstantiateandregisterthebean//(i.e.viaagetBean()call)->invokethesuperimplementationofthemethodtoactually//createthebeaninstance.if(logger.isInfoEnabled()sBeanFactoryPostProcessorinterface.Thiswill"+"resultinafailuretoprocessannotationssuchas@Autowired,"+"@Resourceand@PostConstructwithinthemethodsdeclaring"+"@Configurationclass.Addthestaticmodifiertothismethodtoavoid"+"thesecontainerlifecycleissues;see@Beanjavadocforcompletedetails.",beanMethod.getDeclaringClass().getSimpleName(),beanMethod.getName()));}returncglibMethodProxy.invokeSuper(enhancedConfigInstance,beanMethodArgs);}returnresolveBeanReference(beanMethod,beanMethodArgs,beanFactory,beanName);}此方法会通过getBean来获取对象,这样就可以控制对象的生成了。
privateObjectresolveBeanReference(MethodbeanMethod,Object[]beanMethodArgs,ConfigurableBeanFactorybeanFactory,StringbeanName){//Theuser(i.e.notthefactory)isrequestingthisbeanthroughacallto//thebeanmethod,directorindirect.Thebeanmayhavealreadybeenmarked//asincreationincertainautowiringscenarios;ifso,temporarilyset//thein-creationstatustofalseinordertoavoidanexception.booleanalreadyInCreation=beanFactory.isCurrentlyInCreation(beanName);try{if(alreadyInCreation){beanFactory.setCurrentlyInCreation(beanName,false);}booleanuseArgs=!ObjectUtils.isEmpty(beanMethodArgs);if(useArgsbreak;}}}//通过getBean就可以控制对象的生成,对象如果生成过,则可以直接从一级缓存中获取ObjectbeanInstance=(useArgs?beanFactory.getBean(beanName,beanMethodArgs):beanFactory.getBean(beanName));if(!ClassUtils.isAssignableValue(beanMethod.getReturnType(),beanInstance)){//Detectpackage-protectedNullBeaninstancethroughequals(null)checkif(beanInstance.equals(null)){if(logger.isDebugEnabled()){logger.debug(String.format("@Beanmethod%s.%scalledasbeanreference"+"fortype[%s]returnednullbean;resolvingtonullvalue.",beanMethod.getDeclaringClass().getSimpleName(),beanMethod.getName(),beanMethod.getReturnType().getName()));}beanInstance=null;}else{Stringmsg=String.format("@Beanmethod%s.%scalledasbeanreference"+"fortype[%s]butoverriddenbynon-compatiblebeaninstanceoftype[%s].",beanMethod.getDeclaringClass().getSimpleName(),beanMethod.getName(),beanMethod.getReturnType().getName(),beanInstance.getClass().getName());try{BeanDefinitionbeanDefinition=beanFactory.getMergedBeanDefinition(beanName);msg+="Overridingbeanofsamenamedeclaredin:"+beanDefinition.getResourceDescription();}catch(NoSuchBeanDefinitionExceptionex){//Ignore-simplynodetailedmessagethen.}thrownewIllegalStateException(msg);}}MethodcurrentlyInvoked=SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();if(currentlyInvoked!=null){StringouterBeanName=BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);beanFactory.registerDependentBean(beanName,outerBeanName);}returnbeanInstance;}finally{if(alreadyInCreation){beanFactory.setCurrentlyInCreation(beanName,true);}}}【文章原创作者:欧洲服务器 http://www.558idc.com/helan.html 复制请保留原URL】