当前位置: 首页 > 后端技术 > Java

(1)AOP如何注入SpringBoot?

时间:2023-04-01 20:11:01 Java

主要内容SpringBoot是如何将AOP相关的类注入到BeanFactory中的,它是如何工作的?总结AopAutoConfiguration:自动注入AOP相关的配置类;AnnotationAwareAspectJAutoProxyCreator;populateBean时,每个bean都会扫描是否有section,并进行匹配;AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization;如果匹配成功,将通过cglib动态代理生成一个新的代理类;具体源码流程1.1自动配置类加载AOP相关类;加载AopAutoConfiguration时,加载CglibAutoProxyFactory时,有一个注解@EnableAspectJAutoProxy,有一个@Import注解,AspectJAutoProxyRegistrar;这个注册商很重要!!!其在ConfigurationClassPostProcessor类扫描加载bean的时候,处理loadBeanDefinitionsFromRegistrars的时候;加载进去;publicvoidregisterBeanDefinitions(AnnotationMetadataimportingClassMetadata,BeanDefinitionRegistryregistry){AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);.....registerAspectJAnnotationAutoProxyCreatorIfNecessary()的时候,把AnnotationAwareAspectJAutoProxyCreator封装BeanDefinition,对应key=internalAutoProxyCreator;@NullablepublicstaticBeanDefinitionregisterAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistryregistry,@NullableObjectsource){//将AnnotationAwareAspectJAutoProxyCreator封装成一个BeanDefinition;返回registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class,registry,source);调用所有BeanPostProcessor.postProcessAfterInitialization;其中,会调用AnnotationAwareAspectJAutoProxyCreator;检查是否有符合要求的切面方法;调用方法如下:protectedObjectwrapIfNecessary(Objectbean,StringbeanName,ObjectcacheKey){...//重点如下:找到这个bean的所有切面方法,然后调用createProxy创建代理类;只是返回。//如果我们有建议,则创建代理。Object[]specificInterceptors=getAdvicesAndAdvisorsForBean(bean.getClass(),beanName,null);if(specificInterceptors!=DO_NOT_PROXY){this.advisedBeans.put(cacheKey,Boolean.TRUE);Objectproxy=createProxy(bean.getClass(),beanName,specificInterceptors,newSingletonTargetSource(bean));this.proxyTypes.put(cacheKey,proxy.getClass());返回代理;}this.advisedBeans.put(cacheKey,Boolean.FALSE);返回豆;}1.3找到所有合适的通知protectedListfindEligibleAdvisors(ClassbeanClass,StringbeanName){//1找到所有候选建议ListcandidateAdvisors=findCandidateAdvisors();//2匹配看是否合适ListeligibleAdvisors=findAdvisorsThatCanApply(candidateAdvisors,beanClass,beanName);扩展顾问(合格顾问);if(!eligibleAdvisors.isEmpty()){//3在这里排序顾问?eligibleAdvisors=sortAdvisors(eligibleAdvisors);}返回eligibleAdvisors;}1.3.1findCandidateAdvisorsprotectedListfindCandidateAdvisors(){//添加所有根据超类规则找到的Spring顾问。Listadvisors=super.找到CandidateAdvisors();//为bean工厂中的所有AspectJ方面构建顾问程序。if(this.aspectJAdvisorsBuilder!=null){//开始寻找@AspectJ注解类;advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());返回顾问;}this.aspectJAdvisorsBuilder.buildAspectJAdvisors()主要逻辑:遍历BeanDefinitionMap看是否有@AspectJ注解。如果有,它会遍历方法看是否是通知。如果是通知,会封装成一个InstantiationModelAwarePointcutAdvisorImpl类;然后包裹退货;这个方法也有排序!!在getAdvisorMethod中privateListgetAdvisorMethods(ClassaspectClass){Listmethods=newArrayList<>();ReflectionUtils.doWithMethods(aspectClass,methods::add,adviceMethodFilter);如果(methods.size()>1){methods.sort(adviceMethodComparator);}返回方法;按什么排序?privatestaticfinalComparatoradviceMethodComparator;static{//注意:虽然@After排在@Aft之前erReturning和@AfterThrowing,//@After建议方法实际上将在@AfterReturning和//@AfterThrowing方法之后调用,因为AspectJAfterAdvice.invoke(MethodInvocation)//在`try`块中调用proceed()且仅//在相应的`finally`块中调用@After建议方法。ComparatoradviceKindComparator=newConvertingComparator<>(newInstanceComparator<>(Around.class,Before.class,After.class,AfterReturning.class,AfterThrowing.class),(Converter)方法->{AspectJAnnotationann=AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(方法);返回(ann!=null?ann.getAnnotation():null);});比较器<方法>methodNameComparator=newConvertingComparator<>(Me方法::获取名称);adviceMethodComparator=adviceKindComparator.thenComparing(methodNameComparator);}我们发现是按Around,Before,After,AfterReturning排序的,如果有相同的,则按methodName排序;1.3.2findAdvisorsThatCanApply检查该类是否与PointCut匹配成功,匹配成功则返回列表;protectedListfindAdvisorsThatCanApply(ListcandidateAdvisors,ClassbeanClass,StringbeanName){ProxyCreationContext.setCurrentProxiedBeanName(beanName);}try{//检查这个类是否与PointCut匹配成功,匹配成功,即ok;返回AopUtils.findAdvisorsThatCanApply(candidateAdvisors,beanClass);}最后{ProxyCreationContext.setCurrentProxiedBeanName(null);}}1.3.3findAdvisorsThatCanApply比较两个类的订单大小;Chase,主题逻辑:找到所有Advisor,创建指定的拦截器,例如:在回调方法中加入dynamicAdvisorInterceptor;增强器.create();总结先想一想再做;命名艺术,AutoProxyCreator,AspectJAdvisor,AspectJAdvisorBuilder,XXFactory封装成对象,方便以后扩展