欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Spring@Async的使用與實現(xiàn)的示例代碼

首先Spring AOP有兩個重要的基礎接口,Advisor和PointcutAdvisor,接口聲明如下:

成都創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務,包含不限于成都做網(wǎng)站、網(wǎng)站設計、永靖網(wǎng)絡推廣、小程序制作、永靖網(wǎng)絡營銷、永靖企業(yè)策劃、永靖品牌公關、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運營等,從售前售中售后,我們都將竭誠為您服務,您的肯定,是我們最大的嘉獎;成都創(chuàng)新互聯(lián)公司為所有大學生創(chuàng)業(yè)者提供永靖建站搭建服務,24小時服務熱線:18980820575,官方網(wǎng)址:chinadenli.net

Advisor接口聲明:

public interface Advisor {
  Advice getAdvice();
  boolean isPerInstance();

}

PointcutAdvisor的接口聲明:

public interface PointcutAdvisor extends Advisor {

  /**
   * Get the Pointcut that drives this advisor.
   */
  Pointcut getPointcut();

}

PointcutAdvisor用來獲取一個切點以及這個切點的處理器(Advise)。

@Async注解使用后置處理器BeanPostProcessor的子類AsyncAnnotationBeanPostProcessor來實現(xiàn)bean處理 :

AsyncAnnotationAdvisor繼承了PointcutAdvisor接口。并且在AsyncAnnotationBeanPostProcessor實現(xiàn)了其父類接口的BeanFactoryAware中的setBeanFactory初始化。Spring一旦創(chuàng)建beanFactory回調(diào)成功,就會回調(diào)這個方法。保證Advisor對象最先被初始化。

  @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;
  }

}

具體的后置處理是通過AsyncAnnotationBeanPostProcessor的后置bean處理是通過其父類AbstractAdvisingBeanPostProcessor來實現(xiàn)的。AbstractAdvisingBeanPostProcessor提供的后置bean處理方法對所有的自定義注解的bean處理方法時通用的。其具體的代碼如下:

@Override
  public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean instanceof AopInfrastructureBean) {
      // Ignore AOP infrastructure such as scoped proxies.
      return bean;
    }
   
   /*
   
   * bean對象如果是一個ProxyFactory對象。ProxyFactory繼承了AdvisedSupport,而    AdvisedSupport又繼承了Advised接口。這個時候就把不同的Advisor添加起來。
   *
    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());
    }

可以看得出來,isEligible用于判斷這個類或者這個類中的某個方法是否含有注解。這個方法最終進入到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對象。然后調(diào)用AsyncAnnotationAdvisor對象的getPointcut()方法,得到了Pointcut對象。在AOP規(guī)范中間,表示一個具體的切點。那么在方法上注釋@Async注解,就意味著聲明了一個切點。

然后再根據(jù)Pointcut判斷是否含有指定的注解。

切點的執(zhí)行

由于生成了JDK動態(tài)代理對象,那么每一個方法的執(zhí)行必然進入到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);
      }
    }
  }

重點的執(zhí)行語句:

// 獲取攔截器
      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ù)攔截器來執(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(切點的處理器)。

自定義注解

由于其bean處理器是通用的,所以只要實現(xiàn)PointcutAdvisor和具體的處理器就好了。首先自定義一個注解,只要方法加入了這個注解,就可以輸出這個方法的開始時間和截止時間,注解的名字叫做@Log:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {

}

定義一個簡單的方法用于測試:

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("開始執(zhí)行");
    Object result = invocation.proceed();
    System.out.println("結(jié)束執(zhí)行");
    return result;
  }

}

定義@Log專屬的BeanPostProcesser對象:

@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;
  }



}

對bean的后置處理方法直接沿用其父類的方法。當然也可以自定義其后置處理方法,那么就需要自己判斷這個對象的方法是否含有注解,并且生成代理對象:

@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;

  }

測試注解是否是正常運行的:

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
     
    
  }
}

輸出:

開始執(zhí)行
main
3
結(jié)束執(zhí)行
DemoServiceImpl.getName

功能一切正常。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

網(wǎng)站欄目:Spring@Async的使用與實現(xiàn)的示例代碼
瀏覽路徑:http://chinadenli.net/article6/jeipog.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、企業(yè)建站、網(wǎng)站策劃、自適應網(wǎng)站、移動網(wǎng)站建設、微信公眾號

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設
久久青青草原中文字幕| 国产成人精品一区二三区在线观看| 搡老熟女老女人一区二区| 国产av一区二区三区四区五区| 国产又大又硬又粗又黄| 亚洲熟妇熟女久久精品| 中文字幕亚洲精品在线播放| 欧美成人黄色一区二区三区| 亚洲国产成人一区二区在线观看| 日本熟妇五十一区二区三区| 国产a天堂一区二区专区| 亚洲国产成人精品福利| 99久久人妻中文字幕| 日韩中文高清在线专区| 少妇淫真视频一区二区| 高清不卡一卡二卡区在线| 亚洲淫片一区二区三区| 亚洲一区二区三区在线免费| 日本一二三区不卡免费| 国产精品午夜福利免费在线| 一本色道久久综合狠狠躁| 中文精品人妻一区二区| 人人妻人人澡人人夜夜| 欧美日韩高清不卡在线播放| 国产伦精品一区二区三区高清版 | 亚洲另类欧美综合日韩精品| 国产日本欧美特黄在线观看| 日韩性生活视频免费在线观看| 亚洲黑人精品一区二区欧美| 日韩一区二区三区免费av| 国内外免费在线激情视频| 青青操精品视频在线观看| 91国自产精品中文字幕亚洲| 这里只有九九热精品视频| 国产成人国产精品国产三级| 国产精品国产亚洲区久久| 91人妻人人精品人人爽| 一区二区福利在线视频| 婷婷亚洲综合五月天麻豆| 国产伦精品一区二区三区精品视频| 欧美黑人在线精品极品|