java annotation学习

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
} 

@interface:声明这是一个注解

@Retention:声明注解的策略,可参见RetentionPolicy。SOURCE

public enum RetentionPolicy {
    ###保存在源代码中,会被编译器抛弃
    SOURCE,
    ###编译时生效,会对代码最后生成的class有一定影响,在运行时则不保留。此值为默认值
    CLASS,
    ###编译时生效,会对代码最后生成的class有一定影响,在运行时保留,通常通过反射读取。
    RUNTIME
}
@Target:声明注解可以被放在什么样的元素上面,详见ElementType

如果需要加入一个叫做age的变量,则代码如下:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
  int age();
} 


写个RetentionPolicy=CLASS的注解,通过javac来试一下

注解
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface Assignment {
    String assignee();
} 
注解process
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("Assignment")
public class AssignmentProcess extends AbstractProcessor {
    private TypeElement assignmentElement; 
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        Elements elementUtils = processingEnv.getElementUtils();
        assignmentElement = elementUtils.getTypeElement("Assignment");
    } 
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(assignmentElement);
        for (Element element : elements) {
            System.out.println(element);
        }
        return true;
    }
}  

@Assignment(assignee = "123")
public class Demo1 {
}
执行:
javac -processor AssignmentProcess Demo1.java

Demo1
按道理来说一切正常,不过悲剧的是把注解的retention改成source还是可以执行的,按照前面的理解,source的应该在编译器中读不到的
@Retention(RetentionPolicy.SOURCE)

对Assignment的retention进行修改,看编译后Demo1的class文件

挺正常的样子

@Retention(RetentionPolicy.SOURCE)
public class Demo1 extends java.lang.Object
  SourceFile: "Demo1.java"
@Retention(RetentionPolicy.CLASS)
public class Demo1 extends java.lang.Object
  SourceFile: "Demo1.java"
  RuntimeInvisibleAnnotations: length = 0xB
   00 01 00 0B 00 01 00 0C 73 00 0D 
@Retention(RetentionPolicy.RUNTIME)
public class Demo1 extends java.lang.Object
  SourceFile: "Demo1.java"
  RuntimeVisibleAnnotations: length = 0xB
   00 01 00 0B 00 01 00 0C 73 00 0D 

问题木找到,待研究。



写个RetentionPolicy=RUNTIME的注解试一下

注释
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RoleCheck {
    String role();
} 
handle,内部通过反射取得注释信息,验证是否可以调用该方法
public class AccessInvocationHandler implements InvocationHandler {
    final Object accessObj;
    public AccessInvocationHandler(Object accessObj){
        this.accessObj = accessObj;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        RoleCheck annotation = method.getAnnotation(RoleCheck.class); // 通过反射API获取注解
        if (annotation != null) {
            String role = annotation.role();
            if (!StringUtil.equals(role, CurrentRoleUtil.getCurrentRole())) {
                throw new AccessControlException("The user is not allowed to invoke this method.");
            }
            return method.invoke(accessObj, args);
        } else {
            throw new AccessControlException("The user is not allowed to invoke this method.");
        }
    }
}
模拟cache等工具,获取当前执行的role
public class CurrentRoleUtil {
    private static int cur = 0;
    public static String getCurrentRole(){
        if(cur%2==0){
            ++cur;
            return "guanfei";
        }
        ++cur;
        return "hake";
    }
}
通过代理调用
    public static void main(String[] args) {
        HelloWorld hello = new HelloWorldImpl();
        InvocationHandler handler = new AccessInvocationHandler(hello);
        HelloWorld proxy = (HelloWorld)Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler);
        proxy.sayHello();
        proxy.sayHello();
    }

执行结果
Hello World!
Exception in thread "main" java.security.AccessControlException: The user is not allowed to invoke this method.
	at AccessInvocationHandler.invoke(AccessInvocationHandler.java:20)
	at $Proxy0.sayHello(Unknown Source)
	at Test.main(Test.java:11)

   
   
如果把注释的@Retention(RetentionPolicy.CLASS)
Exception in thread "main" java.security.AccessControlException: The user is not allowed to invoke this method.
	at AccessInvocationHandler.invoke(AccessInvocationHandler.java:24)
	at $Proxy0.sayHello(Unknown Source)
	at Test.main(Test.java:9)

通过反射不能取到该注释











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值