基于Spring注解@AspectJ的AOP

添加依赖

<!-- aspectj 方式的AOP,需要加入下面三个包 -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>1.8.9</version>
        </dependency>

XML启用

Spring上下文创建一个AnnotationAwareAspectJAutoProxyCreator类

<aop:aspectj-autoproxy/>

切入点声明

@AspectJ风格的命名切入点使用org.aspectj.lang.annotation包下的@Pointcut方法(方法必须是返回void类型)实现。

@Pointcut(value="切入点表达式", argNames = "参数名列表")  

使用注解 


  @Pointcut("@annotation(com.apus.dap.hella.common.aspect.annotation.JmxMetrical) || @target(com.apus.dap.hella.common.aspect.annotation.JmxMetrical)")
  public void annotationProcessor() {
  }

 注解类@JmxMetrical 

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

  String name() default "";

  boolean displayArgs() default false;
  /**
   * 增删改的数据的类型
   */
  Class<?> clazz();
}

通知声明

  • 前置通知

使用org.aspectj.lang.annotation 包下的@Before注解声明;
@Before(value = "切入点表达式或命名切入点", argNames = "参数列表参数名")

  • 环绕通知

像Spring基于XML的AOP一样,@AspectJ注解的使用不仅只限定与定义前置和后置通知类型。我们还可以创建环绕通知,使用环绕通知需要使用@Around。

@Around (  
value="切入点表达式或命名切入点",  
argNames="参数列表参数名")

  • 后置返回通知

使用org.aspectj.lang.annotation 包下的@AfterReturning注解声明;

@AfterReturning(  
value="切入点表达式或命名切入点",  
pointcut="切入点表达式或命名切入点",  
argNames="参数列表参数名",  
returning="返回值对应参数名")

  • 后置最终通知

使用org.aspectj.lang.annotation 包下的@After注解声明;
@After (  
value="切入点表达式或命名切入点",  
argNames="参数列表参数名")

扫描二维码关注公众号,回复: 4428317 查看本文章
  • 后置异常通知

使用org.aspectj.lang.annotation 包下的@AfterThrowing注解声明

@AfterThrowing (  
value="切入点表达式或命名切入点",  
pointcut="切入点表达式或命名切入点",  
argNames="参数列表参数名",  
throwing="异常对应参数名") 

@Aspect
  @Component
  public class JmxMetricalAOP {

    private static final Logger LOG = LoggerFactory.getLogger(JmxMetricalAOP.class);


    private static MetricalCounterManager metricalCounterManager;

    private static final String POINTCUT_METHOD =
        "(execution(public * " + API_PROTOCOL_CLASS_NAME + ".*(..)))";

    @PostConstruct
    public void init() {
      //初始化一个全局度量器管理类
      metricalCounterManager = new MetricalCounterManager(Maps.newHashMap());
      LOG.info("JmxMetricalAOP.methodAnnotated init:success");
    }

    @Pointcut("@annotation(com.apus.dap.hella.common.aspect.annotation.JmxMetrical) || @target(com.apus.dap.hella.common.aspect.annotation.JmxMetrical)")
    public void annotationProcessor() {
    }

    @Pointcut(POINTCUT_METHOD)
    public void publicMethod() {
      LOG.info("JmxMetricalAOP.methodJoinPointed");
    }

    @Around("publicMethod() && annotationProcessor()")
    public Object timedJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
      Signature signature = joinPoint.getSignature();
      Method method = ((MethodSignature) signature).getMethod();
      final String methodName = signature.getName();

      /**
       * 1.获取唯一接口全路径
       */
      String fullApiName = getFullApiName(joinPoint, signature, methodName);

      if (method.getDeclaringClass().isInterface()) {
        method = joinPoint.getTarget().getClass()
            .getDeclaredMethod(methodName, method.getParameterTypes());
      }

      /**
       * 2. 方法上的注解优先级比类上的注解高,可以覆盖类上注解的值,获取相关值
       */
      //是否注解
      Boolean isJmxMetrical = false;
      //注解对象名
      String jmxMetricalName = null;
      //注解对象参数
      Object[] jmxMetricalArgs = null;
      //注解对象class
      Class<? extends JmxMetrical> aClass = null;

      JmxMetrical jmxMetrical = null;
      //处理方法上的注解
      if (method.isAnnotationPresent(JmxMetrical.class)) {
        isJmxMetrical = true;
        jmxMetrical = method.getAnnotation(JmxMetrical.class);
        jmxMetricalName = jmxMetrical.name();
        aClass = jmxMetrical.getClass();
        if (jmxMetrical.displayArgs()) {
          jmxMetricalArgs = joinPoint.getArgs();
        }
      } else {
        //处理类上面的注解
        Object target = joinPoint.getTarget();
        if (target.getClass().isAnnotationPresent(JmxMetrical.class)) {
          isJmxMetrical = true;
          jmxMetrical = target.getClass().getAnnotation(JmxMetrical.class);
          jmxMetricalName = jmxMetrical.name();
          aClass = jmxMetrical.getClass();
          if (jmxMetrical.displayArgs()) {
            jmxMetricalArgs = joinPoint.getArgs();
          }
        }
      }
      /**
       * 3. 切入点度量
       */
      //切入点方法执行结果
      Object result = null;
      Boolean thrown = false;
      try {
        result = joinPoint.proceed();
      } catch (Throwable throwable) {
        thrown = true;
        //如果需要度量
      }

      //如果不需要度量
      if (!isJmxMetrical) {
        return result;
      }
      metricalCounterManager.metricApi(fullApiName, result, thrown);
      return result;
    }


    private String getFullApiName(ProceedingJoinPoint joinPoint, Signature signature,
        String methodName) {
      //通过包路径方式获取
      String[] packageName = signature.getDeclaringTypeName().split("\\.");
      StringBuilder stringBuilder = new StringBuilder();
      for (int i = 0; i < packageName.length; ++i) {
        if (i < packageName.length - 1) {
          stringBuilder.append(packageName[i].substring(0, 1));
        } else {
          stringBuilder.append(packageName[i]);
        }
        if (i == packageName.length - 1) {
          stringBuilder.append(FULL_POINT_SEP);
          continue;
        }
        stringBuilder.append(".");
      }
      String fullApiName = stringBuilder + signature.getName();
      LOG.info("Executing: " + fullApiName);
      //通过接口方式获取
//    String className = joinPoint.getTarget().getClass().getInterfaces()[0].getName();
//    String fullApiName = className + SEP + methodName;
      return fullApiName;
    }


    /**
     * 后置异常通知
     */
    @AfterThrowing("publicMethod() && annotationProcessor()")
    public void demandRefund() {
      LOG.info("com.apus.hella.protocol.dto.*#{} exception!!!");
    }


    public static List<MetricalCounter> getMonitorList() {
      List<MetricalCounter> monitor_profiles = getMonitorMap().values().stream()
          .collect(Collectors.toList());
      return monitor_profiles;
    }

 

猜你喜欢

转载自blog.csdn.net/Byd_chao/article/details/82894364