的私有实现。
在 JDK 6 中,通过 JSR 269 把自定义注解处理器这一功能进行了规范化,有了新的javax.annotation.processing 这个新的 API。
对 Mirror API 也进行了更新,形成了新的 javax.lang.model 包。
注解处理器的使用也进行了简化,不需要再单独运行 apt 这样的命令行工具,Java 编译器本身就可以完成对注解的处理。
对于同样的功能,如果用 JSR 269 的做法,只需要一个类就可以了。
以下是代码片段: SupportedSourceVersionSourceVersion.RELEASE_6 SupportedAnnotationTypesannotation.Assignment public class AssignmentProcess extends AbstractProcessor private TypeElement assignmentElement public synchronized void initProcessingEnvironment processingEnv super.initprocessingEnv Elements elementUtils processingEnv.getElementUtils assignmentElement elementUtils.getTypeElementannotation.Assignment public boolean processSet annotations RoundEnvironment roundEnv Set elements roundEnv.getElementsAnnotatedWithassignmentElement for Element element : elements processAssignmentelement private void processAssignmentElement element List annotations element.getAnnotationMirrors for AnnotationMirror mirror : annotations if mirror.getAnnotationType.asElement.equalsassignmentElement Map values mirror.getElementValues String assignee String getAnnotationValuevalues assignee //获取注解的值 仔细比较上面两段代码,可以发现它们的基本结构是类似的。
不同之处在于 JDK 6 中通过元注解SupportedAnnotationTypes 来声明所支持的注解类型。
另外描述程序静态结构的 javax.lang.model 包使用了不同的类型名称。
使用的时候也更加简单,只需要通过 javac -processorannotation.pap.AssignmentProcess Demo1.java 这样的方式即可。
上面介绍的这两种做法都是在编译时刻进行处理的。
而有些时候则需要在运行时刻来完成对注解的处理。
这个时候就需要用到 Java 的反射 API。
反射 API提供了在运行时刻读取注解信息的支持。
不过前提是注解的保留策略声明的是运行时。
Java 反射 API 的 AnnotatedElement 接口提供了获取类、方法和域上的注解的实用方法。
比如获取到一个 Class 类对象之后,通过 getAnnotation 方法就可以获取到该类上添加的指定注解类型的注解。
实例分析 下面通过一个具体的实例来分析说明在实践中如何来使用和处理注解。
假定有一个公司的雇员信息系统,从访问控制的角度出发,对雇员的工资的更新只能由具有特定角色的用户才能完成。
考虑到访问控制需求的普遍性,可以定义一个注解来让开发人员方便的在代码中声明访问控制权限。
以下是代码片段: RetentionRetentionPolicy.RUNTIME TargetElementType.METHOD public interface RequiredRoles String value 下一步则是如何对注解进行处理,这里使用的 Java 的反射 API 并结合动态代理。
下面是动态代理中的 InvocationHandler 接口的实现。
以下是代码片段: public class AccessInvocationHandler implements InvocationHandler final T accessObj public AccessInvocationHandlerT accessObj this.accessObj accessObj public Object invokeObject proxy Method method Object args throws Throwable RequiredRoles annotation method.getAnnotationRequiredRoles.class //通过反射 API 获取注解 if annotation null String roles annotation.value String role AccessControl.getCurrentRole if Arrays.asListroles.containsrole throw new AccessControlExceptionThe user is not allowed to invoke this method. return method.invokeaccessObj args 在具体使用的时候,首先要通过 Proxy.newProxyInstance 方法创建一个 EmployeeGateway 的接口的代理类,使用该代理类来完成实际的操作。
上一篇:
2 AVR 开发环境与工具入门
下一篇:
2018年汽车自驾运动营地攻防箭大赛总决赛圆满落幕