注解的优点以及功能
- 动态修改属性
- 动态新增功能(不侵入原代码)
- 动态改变执行逻辑
spring基本配置(略过)
开发定义注解
注解的定义
@Documented
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Patch {
    String  key() default "";
    String  value() default "";
}
注解实现
@Component
@Aspect
public class PatchAspect {
    @After("Patch()")
    public void after(JoinPoint joinPoint)  {
        // 记录参数
    }
    @AfterReturning(pointcut = "Patch()",returning="returnValue")
    public void afterJoinPoint(JoinPoint joinPoint ,Object returnValue){
        // 记录返回值
    }
    @Pointcut("@annotation(注解路径)")
    public void patch(){}
    @Around("Patch()")
    public void around(ProceedingJoinPoint joinPoint){
        try {
            StopWatch sw = new StopWatch();
            sw.start();
            //获取方法参数
            Object[] args = joinPoint.getArgs();
            MethodSignature sign = (MethodSignature) joinPoint.getSignature();
            String[] parameterNames = sign.getParameterNames();
            System.out.println("parameter list: ");
            for (int i = 0; i < parameterNames.length; i++) {
                System.out.println(parameterNames[i] + " = " + args[i]);
                // 这里可以通过参数名配合注解的值直接修改对应的参数 做拦截操作或者参数校验
            }
            //获取注解参数
            Patch annotation =  sign.getMethod().getAnnotation(Patch.class);
            System.out.println("value = " + annotation.value());
            System.out.println("key = " + annotation.key());
            /*
            // 这里可以不知道注解的情况下获取注解
            Annotation[][] annotations;
            try {
                annotations = pjp.getTarget().getClass().
                        getMethod(methodName, parameterTypes).getParameterAnnotations();
            } catch (Exception e) {
                throw new SoftException(e);
            }
            */
            //执行方法
            joinPoint.proceed();
            //方法执行后逻辑
            sw.stop(args);
            System.out.println(sw.prettyPrint());
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}
总结
注解本质意义上就是代码的注释,如果没有实现解析的逻辑那么仅仅是注释。 对于注释有两种方式,一种是编译直接扫描,一种是运行时反射。 注意:基于 java 注解的开发不同于动态语言的简单逻辑,很多时候需要在代码中有效的处理各种类型的判断以及各种未知。
比如在python中类似的功能称为装饰器 下面为python装饰器的实现可能有助于大家更好的理解。
def run_time(func):
    """Decorator for calculating function runtime.
    Arguments:
        func {function}
    Returns:
        function
    """
    def inner(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        ret = time.time() - start
        if ret < 1e-6:
            unit = "ns"
            ret *= 1e9
        elif ret < 1e-3:
            unit = "us"
            ret *= 1e6
        elif ret < 1:
            unit = "ms"
            ret *= 1e3
        else:
            unit = "s"
        print("Total run time is %.1f %s\n" % (ret, unit))
        return res
    return inner
@run_time
def test():
    pass
业务场景使用:
- 代码性能分析 (记录分析入参、返回值以及输出函数执行时间)
- 业务日志记录 (统一记录相同功能的代码块的业务日志)
- 代码段的统一异常处理
- 为已有代码添加额外的逻辑 (在不改动代码的基础之上实现)