首先Spring AOP有兩個(gè)重要的基礎(chǔ)接口,Advisor和PointcutAdvisor,接口聲明如下:
成都創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都做網(wǎng)站、網(wǎng)站設(shè)計(jì)、永靖網(wǎng)絡(luò)推廣、小程序制作、永靖網(wǎng)絡(luò)營(yíng)銷、永靖企業(yè)策劃、永靖品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);成都創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供永靖建站搭建服務(wù),24小時(shí)服務(wù)熱線:18980820575,官方網(wǎng)址:aaarwkj.com
Advisor接口聲明:
public interface Advisor { Advice getAdvice(); boolean isPerInstance(); }
PointcutAdvisor的接口聲明:
public interface PointcutAdvisor extends Advisor { /** * Get the Pointcut that drives this advisor. */ Pointcut getPointcut(); }
PointcutAdvisor用來(lái)獲取一個(gè)切點(diǎn)以及這個(gè)切點(diǎn)的處理器(Advise)。
@Async注解使用后置處理器BeanPostProcessor的子類AsyncAnnotationBeanPostProcessor來(lái)實(shí)現(xiàn)bean處理 :
AsyncAnnotationAdvisor繼承了PointcutAdvisor接口。并且在AsyncAnnotationBeanPostProcessor實(shí)現(xiàn)了其父類接口的BeanFactoryAware中的setBeanFactory初始化。Spring一旦創(chuàng)建beanFactory回調(diào)成功,就會(huì)回調(diào)這個(gè)方法。保證Advisor對(duì)象最先被初始化。
@Override public void setBeanFactory(BeanFactory beanFactory) { super.setBeanFactory(beanFactory); AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler); if (this.asyncAnnotationType != null) { advisor.setAsyncAnnotationType(this.asyncAnnotationType); } advisor.setBeanFactory(beanFactory); this.advisor = advisor; } }
具體的后置處理是通過(guò)AsyncAnnotationBeanPostProcessor的后置bean處理是通過(guò)其父類AbstractAdvisingBeanPostProcessor來(lái)實(shí)現(xiàn)的。AbstractAdvisingBeanPostProcessor提供的后置bean處理方法對(duì)所有的自定義注解的bean處理方法時(shí)通用的。其具體的代碼如下:
@Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof AopInfrastructureBean) { // Ignore AOP infrastructure such as scoped proxies. return bean; } /* * bean對(duì)象如果是一個(gè)ProxyFactory對(duì)象。ProxyFactory繼承了AdvisedSupport,而 AdvisedSupport又繼承了Advised接口。這個(gè)時(shí)候就把不同的Advisor添加起來(lái)。 * if (bean instanceof Advised) { Advised advised = (Advised) bean; if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) { // Add our local Advisor to the existing proxy's Advisor chain... if (this.beforeExistingAdvisors) { advised.addAdvisor(0, this.advisor); } else { advised.addAdvisor(this.advisor); } return bean; } } if (isEligible(bean, beanName)) { ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName); if (!proxyFactory.isProxyTargetClass()) { evaluateProxyInterfaces(bean.getClass(), proxyFactory); } proxyFactory.addAdvisor(this.advisor); customizeProxyFactory(proxyFactory); return proxyFactory.getProxy(getProxyClassLoader()); }
可以看得出來(lái),isEligible用于判斷這個(gè)類或者這個(gè)類中的某個(gè)方法是否含有注解。這個(gè)方法最終進(jìn)入到AopUtils的canApply方法中間:
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } }
這里的advisor就是AsyncAnnotationAdvisor對(duì)象。然后調(diào)用AsyncAnnotationAdvisor對(duì)象的getPointcut()方法,得到了Pointcut對(duì)象。在AOP規(guī)范中間,表示一個(gè)具體的切點(diǎn)。那么在方法上注釋@Async注解,就意味著聲明了一個(gè)切點(diǎn)。
然后再根據(jù)Pointcut判斷是否含有指定的注解。
切點(diǎn)的執(zhí)行
由于生成了JDK動(dòng)態(tài)代理對(duì)象,那么每一個(gè)方法的執(zhí)行必然進(jìn)入到JdkDynamicAopProxy中的invoke方法中間去執(zhí)行:
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class<?> targetClass = null; Object target = null; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be null. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // Get the interception chain for this method. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // We need to create a method invocation... invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
重點(diǎn)的執(zhí)行語(yǔ)句:
// 獲取攔截器 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // 根據(jù)攔截器來(lái)執(zhí)行 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. retVal = invocation.proceed(); }
@Async注解的攔截器是AsyncExecutionInterceptor,它繼承了MethodInterceptor接口。而MethodInterceptor就是AOP規(guī)范中的Advice(切點(diǎn)的處理器)。
自定義注解
由于其bean處理器是通用的,所以只要實(shí)現(xiàn)PointcutAdvisor和具體的處理器就好了。首先自定義一個(gè)注解,只要方法加入了這個(gè)注解,就可以輸出這個(gè)方法的開(kāi)始時(shí)間和截止時(shí)間,注解的名字叫做@Log:
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Log { }
定義一個(gè)簡(jiǎn)單的方法用于測(cè)試:
public interface IDemoService { void add(int a, int b); String getName(); } @Service public class DemoServiceImpl implements IDemoService { @Log public void add(int a, int b) { System.out.println(Thread.currentThread().getName()); System.out.println(a + b); } @Override public String getName() { System.out.println("DemoServiceImpl.getName"); return "DemoServiceImpl"; } }
定義Advisor:
public class LogAnnotationAdvisor extends AbstractPointcutAdvisor { private Advice advice; private Pointcut pointcut; public LogAnnotationAdvisor() { this.advice = new LogAnnotationInterceptor(); } @Override public Advice getAdvice() { return this.advice; } @Override public boolean isPerInstance() { return false; } @Override public Pointcut getPointcut() { return this.pointcut; } public void setAsyncAnnotationType(Class<? extends Annotation> asyncAnnotationType) { Assert.notNull(asyncAnnotationType, "'asyncAnnotationType' must not be null"); Set<Class<? extends Annotation>> asyncAnnotationTypes = new HashSet<Class<? extends Annotation>>(); asyncAnnotationTypes.add(asyncAnnotationType); this.pointcut = buildPointcut(asyncAnnotationTypes); } protected Pointcut buildPointcut(Set<Class<? extends Annotation>> asyncAnnotationTypes) { ComposablePointcut result = null; for (Class<? extends Annotation> asyncAnnotationType : asyncAnnotationTypes) { Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true); Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(asyncAnnotationType); if (result == null) { result = new ComposablePointcut(cpc).union(mpc); } else { result.union(cpc).union(mpc); } } return result; } }
定義具體的處理器:
public class LogAnnotationInterceptor implements MethodInterceptor, Ordered { @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("開(kāi)始執(zhí)行"); Object result = invocation.proceed(); System.out.println("結(jié)束執(zhí)行"); return result; } }
定義@Log專屬的BeanPostProcesser對(duì)象:
@SuppressWarnings("serial") @Service public class LogAnnotationBeanPostProcesser extends AbstractBeanFactoryAwareAdvisingPostProcessor { @Override public void setBeanFactory(BeanFactory beanFactory) { super.setBeanFactory(beanFactory); LogAnnotationAdvisor advisor = new LogAnnotationAdvisor(); advisor.setAsyncAnnotationType(Log.class); this.advisor = advisor; } }
對(duì)bean的后置處理方法直接沿用其父類的方法。當(dāng)然也可以自定義其后置處理方法,那么就需要自己判斷這個(gè)對(duì)象的方法是否含有注解,并且生成代理對(duì)象:
@Override public Object postProcessAfterInitialization(Object bean, String beanName) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(bean.getClass()); for (Method method : methods) { if (method.isAnnotationPresent(Log.class)) { ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName); System.out.println(proxyFactory); if (!proxyFactory.isProxyTargetClass()) { evaluateProxyInterfaces(bean.getClass(), proxyFactory); } proxyFactory.addAdvisor(this.advisor); customizeProxyFactory(proxyFactory); return proxyFactory.getProxy(getProxyClassLoader()); } } return bean; }
測(cè)試注解是否是正常運(yùn)行的:
public class Main { public static void main(String[] args) { @SuppressWarnings("resource") ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml"); IDemoService demoService = context.getBean(IDemoService.class); demoService.add(1, 2); demoService.getName(); //// AsyncAnnotationAdvisor // AsyncAnnotationBeanPostProcessor } }
輸出:
開(kāi)始執(zhí)行 main 3 結(jié)束執(zhí)行 DemoServiceImpl.getName
功能一切正常。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
網(wǎng)站欄目:Spring@Async的使用與實(shí)現(xiàn)的示例代碼
瀏覽路徑:http://aaarwkj.com/article6/jeipog.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、企業(yè)建站、網(wǎng)站策劃、自適應(yīng)網(wǎng)站、移動(dòng)網(wǎng)站建設(shè)、微信公眾號(hào)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)