zoukankan      html  css  js  c++  java
  • java注解

    注解使用

      Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
      注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。包含在 java.lang.annotation 包中。

    元注解

      元注解是指注解的注解。包括  @Retention 、@Target 、@Document 、@Inherited四种。

     @Retention: 定义注解的保留策略

      @Retention(RetentionPolicy.SOURCE)   //注解仅存在于源码中,在class字节码文件中不包含
        @Retention(RetentionPolicy.CLASS)     // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
        @Retention(RetentionPolicy.RUNTIME)  // 注解会在class字节码文件中存在,在运行时可以通过反射获取到

    @Target(ElementType)有:

       1.CONSTRUCTOR:用于描述构造器
      2.FIELD:用于描述域
      3.LOCAL_VARIABLE:用于描述局部变量
      4.METHOD:用于描述方法
      5.PACKAGE:用于描述包
      6.PARAMETER:用于描述参数
      7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

    @Documented

      @Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

    @Inherited

      @Inherited 作用是,使用此注解声明出来的自定义注解,在使用此自定义注解时,如果注解在类或接口上面时,子类会自动继承此注解,否则的话,子类不会继承此注解。使用Inherited声明出来的注解,只有在类上使用时才会有效,对方法,属性等其他无效

    无参数注解

    自定义无参数注解:

    
    
    package com.xxx.annotation;
    /**
     * Created by yang
     * 2016/7/25.
     */
    public @interface ApiLog {
    }

     注解处理方法:

    @Aspect
    @Component
    @Order(1)
    public class ApiAspect {
        /**
         * 日志拦截处理,主要实现打印输入参数和输出参数
         * @param pjp
         * @return
         * @throws Throwable
         */
        @Around("execution(@com.xxx.annotation.ApiLog * *(..))")
        public Object auditMethodCallLog(ProceedingJoinPoint pjp) throws Throwable {
    
        }
    }

    注解传参数

    可以同时指定应用于多个Target,eg:

    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
    @Retention(RUNTIME)
    @Documented

    自定义注解:

    /**
     * @author yang
     * @date 2017/10/23
     */
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface TestAnnotation {
        String[] value() default {};
    
        String description() default "";
    
        boolean defaultPass() default false;
    }

    1、注解作为参数传递:

    注解处理方法:

    @Aspect
    @Component
    public class TestAnnotationAspect {
        @Around( value="@annotation(testAnnotation)",argNames="pjp,testAnnotation")
        public Object testAspect(ProceedingJoinPoint pjp, TestAnnotation testAnnotation) throws Throwable {
            String des = testAnnotation.description();
            System.out.print(testAnnotation);
            return pjp.proceed();
        }
    }

    2、注解参数:(获取方法的当前注解对象)

    @Slf4j
    @Aspect
    @Component
    @Order(999)
    public class TestAspect {
        @AfterReturning(value = "execution(@com.ppdai.store.orderapi.site.common.annotation.MetricMonitor * *(..))", returning = "retVal")
        public void getTestAnnotationArgs(JoinPoint jp, Object retVal) {
            try {
                MetricMonitor annotation = jp.getSignature().getDeclaringType().getMethod(jp.getSignature().getName()).getAnnotation(TestAnnotation.class);
                if (annotation != null) {
                    log.info(testAnnotation.description());
                }
            } catch (Exception ex) {
                log.error(this.getClass().getName() + " error !", ex);
            }
        }
    }

    验证传参:

    @TestAnnotation注解传入参数:

        @RequestMapping("/test")
        @TestAnnotation(description = "test description",defaultPass = true)
        public String test() {
            return "home";
        }

    注解处理方法输出:

    @com.demo.projects.common.TestAnnotation(defaultPass=true, value=[], description=test description)

    注解 + 拦截器

     登陆注解:

    /**
     * @author yang
     * @date 2017/10/23
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface AuthLogin {
        String redirectUrl() default "";
    }

    登陆拦截器+注解:

    /**
     * @author yang
     * @date 2017/10/23
     */
    public class AuthLoginInteceptor extends HandlerInterceptorAdapter {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            if (handler instanceof HandlerMethod) {
                HandlerMethod myHandlerMethod = (HandlerMethod) handler;
                Method method = myHandlerMethod.getMethod();
                AuthLogin authFlag = method.getAnnotation(AuthLogin.class);
                System.out.print(authFlag);
                boolean login = false;
                if (authFlag != null) {
                    String redirectUrl = "http://www.demo.com";
                    if(!StringUtils.isEmpty(authFlag.redirectUrl())){
                        redirectUrl = authFlag.redirectUrl();
                    }
                    if(!login) {//未登录
                        String redirectLoginUrl = "https://test.login.com/Login?redirect=" + URLEncoder.encode(redirectUrl, "utf-8");
                        response.sendRedirect(redirectLoginUrl);
                        return false;
                    }
                }
                return true;
            }
            return super.preHandle(request, response, handler);
        }
    }

    spring boot配置拦截器:

    /**
     * Created by yang on 2017/6/6.
     */
    @Configuration
    public class MyMvcConfiguration extends WebMvcConfigurerAdapter {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new AuthLoginInteceptor()).addPathPatterns("/**");
            super.addInterceptors(registry);
        }
    }

    登陆注解使用:

        @RequestMapping("/login")
        @AuthLogin(redirectUrl = "http://www.baidu.com")
        public String loginAuth() {
            return "home";
        }

    注解处理方法输出:

    @com.demo.projects.common.AuthLogin(redirectUrl=http://www.baidu.com)

    获取注解参数

    1、通过反射来获取

    eg1:

    TestAnnotation annotation = jp.getSignature().getDeclaringType().getMethod(jp.getSignature().getName()).getAnnotation(TestAnnotation.class);

    eg2:(上面例子登录拦截器的示例)

    HandlerMethod myHandlerMethod = (HandlerMethod) handler;

    Method method = myHandlerMethod.getMethod();
    TestAnnotation authFlag = method.getAnnotation(TestAnnotation.class);

    2、通过参数直接传递

    @AfterReturning(value = "@annotation(testAnnotation)", argNames = "jp,testAnnotation,retVal", returning = "retVal")
    public void afterProcess(JoinPoint jp, TestAnnotation testAnnotation, Object retVal) {

      //TODO:

    }

    通用拦截器

    拦截指定的包下的所有的方法,如拦截包:com.demo.controller.api 下的所有方法

    @Around("execution(* com.demo.controller.api.*.* (..))")

    多拦截器是否会多次调用目标方法?

    如下示例:

    Aspect1:

    @Aspect
    @Component
    @Order(1)
    public class ApiAspect1 {
        @Around("execution(* com.demo.controller.api.*.* (..))")
       public Object auditMethodCallLog(ProceedingJoinPoint pjp) throws Throwable { System.out.println("ApiAspect1 begin=================="); Object retVal = pjp.proceed(); System.out.println("ApiAspect1 finished==============="); return retVal; } }

    Aspect2:

    @Aspect
    @Component
    @Order(0)
    public class ApiAspect2 {
        @Around("execution(* com.demo.controller.api.*.* (..))")
        public Object auditMethodCallLog(ProceedingJoinPoint pjp) throws Throwable {
    
            System.out.println("ApiAspect2 begin==================");
            Object retVal = pjp.proceed();
            System.out.println("ApiAspect2 finished===============");
            return retVal;
        }
    }

    目标方法:

        @ApiAspec1
        @ApiAspec2
        public void test() {
            System.out.println("test method execute……");
        }

    首先,Aspect1 和 Aspect2肯定都会拦截test()方法,在test()方法执行前后打印日志;但是两个Aspect都执行了pjp.proceed()是否会触发test()方法执行两次?

    来运行一下代码,输出:

    ApiAspect2 begin==================
    ApiAspect1 begin==================
    test method execute……
    ApiAspect1 finished===============
    ApiAspect2 finished===============

     因为指定了Aspect的Order注解,值越小优先级越高,优先级越高越先执行。

    注解合并、继承

    参考:Java注解合并,注解继承

  • 相关阅读:
    BOMwindow对象
    函数
    js 页面定时刷新
    appcan中 模拟表单上传图片
    商品评价多图片分组上传
    微信发送通知消息 thinkphp
    微信页面的分享,设置分享信息以及监听分享
    微信异步通知出错,behavior原因
    清空session
    json_decode
  • 原文地址:https://www.cnblogs.com/mr-yang-localhost/p/7719689.html
Copyright © 2011-2022 走看看