Spring @Async 的使用与实现的示例代码
首先SpringAOP有两个重要的基础接口,Advisor和PointcutAdvisor,接口声明如下:
Advisor接口声明:
publicinterfaceAdvisor{ AdvicegetAdvice(); booleanisPerInstance(); }
PointcutAdvisor的接口声明:
publicinterfacePointcutAdvisorextendsAdvisor{ /** *GetthePointcutthatdrivesthisadvisor. */ PointcutgetPointcut(); }
PointcutAdvisor用来获取一个切点以及这个切点的处理器(Advise)。
@Async注解使用后置处理器BeanPostProcessor的子类AsyncAnnotationBeanPostProcessor来实现bean处理:
AsyncAnnotationAdvisor继承了PointcutAdvisor接口。并且在AsyncAnnotationBeanPostProcessor实现了其父类接口的BeanFactoryAware中的setBeanFactory初始化。Spring一旦创建beanFactory回调成功,就会回调这个方法。保证Advisor对象最先被初始化。
@Override publicvoidsetBeanFactory(BeanFactorybeanFactory){ super.setBeanFactory(beanFactory); AsyncAnnotationAdvisoradvisor=newAsyncAnnotationAdvisor(this.executor,this.exceptionHandler); if(this.asyncAnnotationType!=null){ advisor.setAsyncAnnotationType(this.asyncAnnotationType); } advisor.setBeanFactory(beanFactory); this.advisor=advisor; } }
具体的后置处理是通过AsyncAnnotationBeanPostProcessor的后置bean处理是通过其父类AbstractAdvisingBeanPostProcessor来实现的。AbstractAdvisingBeanPostProcessor提供的后置bean处理方法对所有的自定义注解的bean处理方法时通用的。其具体的代码如下:
@Override publicObjectpostProcessAfterInitialization(Objectbean,StringbeanName){ if(beaninstanceofAopInfrastructureBean){ //IgnoreAOPinfrastructuresuchasscopedproxies. returnbean; } /* *bean对象如果是一个ProxyFactory对象。ProxyFactory继承了AdvisedSupport,而AdvisedSupport又继承了Advised接口。这个时候就把不同的Advisor添加起来。 * if(beaninstanceofAdvised){ Advisedadvised=(Advised)bean; if(!advised.isFrozen()&&isEligible(AopUtils.getTargetClass(bean))){ //AddourlocalAdvisortotheexistingproxy'sAdvisorchain... if(this.beforeExistingAdvisors){ advised.addAdvisor(0,this.advisor); } else{ advised.addAdvisor(this.advisor); } returnbean; } } if(isEligible(bean,beanName)){ ProxyFactoryproxyFactory=prepareProxyFactory(bean,beanName); if(!proxyFactory.isProxyTargetClass()){ evaluateProxyInterfaces(bean.getClass(),proxyFactory); } proxyFactory.addAdvisor(this.advisor); customizeProxyFactory(proxyFactory); returnproxyFactory.getProxy(getProxyClassLoader()); }
可以看得出来,isEligible用于判断这个类或者这个类中的某个方法是否含有注解。这个方法最终进入到AopUtils的canApply方法中间:
publicstaticbooleancanApply(Advisoradvisor,Class>targetClass,booleanhasIntroductions){ if(advisorinstanceofIntroductionAdvisor){ return((IntroductionAdvisor)advisor).getClassFilter().matches(targetClass); } elseif(advisorinstanceofPointcutAdvisor){ PointcutAdvisorpca=(PointcutAdvisor)advisor; returncanApply(pca.getPointcut(),targetClass,hasIntroductions); } else{ //Itdoesn'thaveapointcutsoweassumeitapplies. returntrue; } }
这里的advisor就是AsyncAnnotationAdvisor对象。然后调用AsyncAnnotationAdvisor对象的getPointcut()方法,得到了Pointcut对象。在AOP规范中间,表示一个具体的切点。那么在方法上注释@Async注解,就意味着声明了一个切点。
然后再根据Pointcut判断是否含有指定的注解。
切点的执行
由于生成了JDK动态代理对象,那么每一个方法的执行必然进入到JdkDynamicAopProxy中的invoke方法中间去执行:
@Override publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{ MethodInvocationinvocation; ObjectoldProxy=null; booleansetProxyContext=false; TargetSourcetargetSource=this.advised.targetSource; Class>targetClass=null; Objecttarget=null; try{ if(!this.equalsDefined&&AopUtils.isEqualsMethod(method)){ //Thetargetdoesnotimplementtheequals(Object)methoditself. returnequals(args[0]); } elseif(!this.hashCodeDefined&&AopUtils.isHashCodeMethod(method)){ //ThetargetdoesnotimplementthehashCode()methoditself. returnhashCode(); } elseif(method.getDeclaringClass()==DecoratingProxy.class){ //ThereisonlygetDecoratedClass()declared->dispatchtoproxyconfig. returnAopProxyUtils.ultimateTargetClass(this.advised); } elseif(!this.advised.opaque&&method.getDeclaringClass().isInterface()&& method.getDeclaringClass().isAssignableFrom(Advised.class)){ //ServiceinvocationsonProxyConfigwiththeproxyconfig... returnAopUtils.invokeJoinpointUsingReflection(this.advised,method,args); } ObjectretVal; if(this.advised.exposeProxy){ //Makeinvocationavailableifnecessary. oldProxy=AopContext.setCurrentProxy(proxy); setProxyContext=true; } //Maybenull.Getaslateaspossibletominimizethetimewe"own"thetarget, //incaseitcomesfromapool. target=targetSource.getTarget(); if(target!=null){ targetClass=target.getClass(); } //Gettheinterceptionchainforthismethod. List
重点的执行语句:
//获取拦截器 List
@Async注解的拦截器是AsyncExecutionInterceptor,它继承了MethodInterceptor接口。而MethodInterceptor就是AOP规范中的Advice(切点的处理器)。
自定义注解
由于其bean处理器是通用的,所以只要实现PointcutAdvisor和具体的处理器就好了。首先自定义一个注解,只要方法加入了这个注解,就可以输出这个方法的开始时间和截止时间,注解的名字叫做@Log:
@Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public@interfaceLog{ }
定义一个简单的方法用于测试:
publicinterfaceIDemoService{ voidadd(inta,intb); StringgetName(); } @Service publicclassDemoServiceImplimplementsIDemoService{ @Log publicvoidadd(inta,intb){ System.out.println(Thread.currentThread().getName()); System.out.println(a+b); } @Override publicStringgetName(){ System.out.println("DemoServiceImpl.getName"); return"DemoServiceImpl"; } }
定义Advisor:
publicclassLogAnnotationAdvisorextendsAbstractPointcutAdvisor{ privateAdviceadvice; privatePointcutpointcut; publicLogAnnotationAdvisor(){ this.advice=newLogAnnotationInterceptor(); } @Override publicAdvicegetAdvice(){ returnthis.advice; } @Override publicbooleanisPerInstance(){ returnfalse; } @Override publicPointcutgetPointcut(){ returnthis.pointcut; } publicvoidsetAsyncAnnotationType(ClassasyncAnnotationType){ Assert.notNull(asyncAnnotationType,"'asyncAnnotationType'mustnotbenull"); Set>asyncAnnotationTypes=newHashSet >(); asyncAnnotationTypes.add(asyncAnnotationType); this.pointcut=buildPointcut(asyncAnnotationTypes); } protectedPointcutbuildPointcut(Set >asyncAnnotationTypes){ ComposablePointcutresult=null; for(ClassasyncAnnotationType:asyncAnnotationTypes){ Pointcutcpc=newAnnotationMatchingPointcut(asyncAnnotationType,true); Pointcutmpc=AnnotationMatchingPointcut.forMethodAnnotation(asyncAnnotationType); if(result==null){ result=newComposablePointcut(cpc).union(mpc); }else{ result.union(cpc).union(mpc); } } returnresult; } }
定义具体的处理器:
publicclassLogAnnotationInterceptorimplementsMethodInterceptor,Ordered{ @Override publicintgetOrder(){ returnOrdered.HIGHEST_PRECEDENCE; } @Override publicObjectinvoke(MethodInvocationinvocation)throwsThrowable{ System.out.println("开始执行"); Objectresult=invocation.proceed(); System.out.println("结束执行"); returnresult; } }
定义@Log专属的BeanPostProcesser对象:
@SuppressWarnings("serial") @Service publicclassLogAnnotationBeanPostProcesserextendsAbstractBeanFactoryAwareAdvisingPostProcessor{ @Override publicvoidsetBeanFactory(BeanFactorybeanFactory){ super.setBeanFactory(beanFactory); LogAnnotationAdvisoradvisor=newLogAnnotationAdvisor(); advisor.setAsyncAnnotationType(Log.class); this.advisor=advisor; } }
对bean的后置处理方法直接沿用其父类的方法。当然也可以自定义其后置处理方法,那么就需要自己判断这个对象的方法是否含有注解,并且生成代理对象:
@Override publicObjectpostProcessAfterInitialization(Objectbean,StringbeanName){ Method[]methods=ReflectionUtils.getAllDeclaredMethods(bean.getClass()); for(Methodmethod:methods){ if(method.isAnnotationPresent(Log.class)){ ProxyFactoryproxyFactory=prepareProxyFactory(bean,beanName); System.out.println(proxyFactory); if(!proxyFactory.isProxyTargetClass()){ evaluateProxyInterfaces(bean.getClass(),proxyFactory); } proxyFactory.addAdvisor(this.advisor); customizeProxyFactory(proxyFactory); returnproxyFactory.getProxy(getProxyClassLoader()); } } returnbean; }
测试注解是否是正常运行的:
publicclassMain{ publicstaticvoidmain(String[]args){ @SuppressWarnings("resource") ClassPathXmlApplicationContextcontext=newClassPathXmlApplicationContext("application-context.xml"); IDemoServicedemoService=context.getBean(IDemoService.class); demoService.add(1,2); demoService.getName(); ////AsyncAnnotationAdvisor //AsyncAnnotationBeanPostProcessor } }
输出:
开始执行 main 3 结束执行 DemoServiceImpl.getName
功能一切正常。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。