@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { }
@interface:声明这是一个注解
@Retention:声明注解的策略,可参见RetentionPolicy。SOURCE
@Target:声明注解可以被放在什么样的元素上面,详见ElementTypepublic enum RetentionPolicy { ###保存在源代码中,会被编译器抛弃 SOURCE, ###编译时生效,会对代码最后生成的class有一定影响,在运行时则不保留。此值为默认值 CLASS, ###编译时生效,会对代码最后生成的class有一定影响,在运行时保留,通常通过反射读取。 RUNTIME }
如果需要加入一个叫做age的变量,则代码如下:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { int age(); }
写个RetentionPolicy=CLASS的注解,通过javac来试一下
注解注解process@Retention(RetentionPolicy.CLASS) @Target(ElementType.TYPE) public @interface Assignment { String assignee(); }
@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 { }
按道理来说一切正常,不过悲剧的是把注解的retention改成source还是可以执行的,按照前面的理解,source的应该在编译器中读不到的javac -processor AssignmentProcess Demo1.java Demo1
@Retention(RetentionPolicy.SOURCE)
对Assignment的retention进行修改,看编译后Demo1的class文件
挺正常的样子
@Retention(RetentionPolicy.SOURCE)@Retention(RetentionPolicy.CLASS)public class Demo1 extends java.lang.Object SourceFile: "Demo1.java"
@Retention(RetentionPolicy.RUNTIME)public class Demo1 extends java.lang.Object SourceFile: "Demo1.java" RuntimeInvisibleAnnotations: length = 0xB 00 01 00 0B 00 01 00 0C 73 00 0D
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,内部通过反射取得注释信息,验证是否可以调用该方法模拟cache等工具,获取当前执行的rolepublic 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."); } } }
通过代理调用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)
通过反射不能取到该注释
java annotation学习
最新推荐文章于 2024-09-01 14:18:24 发布