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
功能一切正常。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。