springmvc的注解大家应该都用过,使用注解相比配置文件更加简单易用,简单介绍一下自定义注解。

  1. 定义一个注解接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package com.interceptor.logger.annotations;
    import java.lang.annotation.*;
    /**
    * 方法调用前后或抛出异常后打出日志的注解
    *
    * Created by Toyr on 16-12-26.
    */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface LogAspects {
    }
    元注解:元注解的作用就是负责注解其他注解。@Target,@Retention,@Documented,@Inherited
    • @Target 注解的使用范围(即:被描述的注解可以用在什么地方)。取值见文章末
    • @Retention 表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
    • @Documented 用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。
    • @Inherited 是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
  2. 定义切面类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    package com.interceptor.logger;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import java.util.Arrays;
    /**
    * 环绕通知 异常通知
    *
    * Created by Toyr on 16-12-26.
    */
    @Aspect
    @Component
    public class LogAspect {
    private static Logger logger = LoggerFactory.getLogger(LogAspect.class);
    @Around("@annotation(com.ai.acodm.base.interceptor.logger.annotations.LogAspects)")
    public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
    Object[] args = pjp.getArgs();
    String className = pjp.getTarget().getClass().getName();
    String methodName = pjp.getSignature().getName();
    logger.info("方法" + className + "#" + methodName + "调用前参数:" + Arrays.asList(args));
    Object retVal = pjp.proceed();
    logger.info("方法" + className + "#" + methodName + "返回结果:" + retVal.toString());
    return retVal;
    }
    @AfterThrowing(pointcut = "@annotation(com.ai.acodm.base.interceptor.logger.annotations.LogAspects)", throwing = "ex")
    public void doThrowing(JoinPoint jp, Throwable ex) {
    String className = jp.getTarget().getClass().getName();
    String methodName = jp.getSignature().getName();
    logger.error("方法" + className + "#" + methodName + "执行中抛出的异常:" + ex);
    }
    }
  3. 使用spring的配置自动完成创建代理织入切面的工作

    1
    2
    <!-- spring通知扫描 -->
    <aop:aspectj-autoproxy/>
取值 范围
CONSTRUCTOR 构造器
FIELD
LOCAL_VARIABLE 局部变量
METHOD 方法
PACKAGE
PARAMETER 参数
TYPE 类、接口(包括注解类型) 或enum声明
取值 生命周期
SOURCE 源文件
CLASS class稳健
RUNTIME 运行时