ARE4j 是一个用于Java的通用Annotation解析引擎。
1. ARE4j提供了一个通用的引擎来解析Annotation;可以用于解析任何类型的自定义annotation;
2. 之所以设计为引擎,而不是框架或者容器,因为这样,可以尽可能少的减少对现有代码的影响,如果你的项目已经很好的应用的工厂模式,那么只需简单的替换或者重写Factory类即可开始使用ARE4j来解析代码中的Annotation;
3.ARE4j只依赖于javassist,这样不会对现有项目带来任何影响;
4.ARE4j非常简单易用;
Scannotation 和 Jandex是另外两个Annotation工具。Scannotation可以在运行时扫描你的Jar和Classpath,并将index存储于内存中;Jandex在编译时刻扫描代码中annotation,并将index存储于文件中。Scannotation和Jandex可以用来发现annotation,并能在运行时提高annotation的索引速度。而ARE4j不同,它是在运行时对Class中的Annotation进行解析,从而实现设计人员对于Annotation所要实现的逻辑。
使用ARE4j是非常简单的,只需要认识Engine类以及几个为了实现Resolver类需要了解的几个接口。
Engine 是ARE4j最核心的类,需要通过Engine类来完成对ARE4j的各种调用。Engine类完成一下功能:
1. register/unregister annotation resolver class
2. Check if annotation reasonable
3. Create proxy object by javassist
4. Cache annotations while parsing class first time
通过调用 Engine.newProxyInstance(Class<? extends T> clazz) 返回的是一个proxy object, 在执行的时候,proxy object会按照要求对 Class/Constructor/Field/Method/Parameter上的Annotation进行解析。
为了实现Annotation的解析逻辑,需要实现各种AnnotationResolver接口,一共有5个接口:
ClassAnnotationResolver, ConstructorAnnotationResolver, FieldAnnotationResolver, MethodAnnotationResolver, ParameterAnnotationResolver。以 MethodAnnotationResolver 为例,为了完整的解析可用于 Method 的 Annotation,需要实现以下的方法:
这3个方法分别会在对象构造之后,方法执行之前以及方法执行之后会被调用,可以实现相关的代码实现Annotation所要期望的逻辑。
接下来看一个简单的Example来看看如何定义Annotation、实现Resolver以及使用Engine,完整的例子可以参考 ARE4j testcase.
1. 定义Annotation
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface TestMethodAnnotation { }
2. 实现 Resolver
public class TestMethodResolver implements MethodAnnotationResolver { public void resolveMethodAnnotationAfterConstruct(MethodResolveContext methodResolveContext) throws ResolverException { } public void resolveMethodAnnotationBeforeMethod(MethodResolveContext methodResolveContext) throws ResolverException { methodResolveContext.setParameters(new String[]{"value2_changed"}); } public void resolveMethodAnnotationAfterMethod(MethodResolveContext methodResolveContext) throws ResolverException { } }
3. 假设一个TestObject需要使用 Annotation
public class TestObject { private Object field2 = "value1"; @TestMethodAnnotation public void setField2_2(Object field2) { this.field2 = field2; } public Object getField2() { return field2; } }
4. TestCase
@Test public void testMethodAnnotation() throws Exception{ Engine.registerAnnotation(TestMethodAnnotation.class, new TestMethodResolver()); TestObject testObject = Engine.newProxyInstance(TestObject.class); testObject.setField2_2(""); // TestMethodResolver will check the init value and set value to "value2_change" Assert.assertEquals("value2_changed", testObject.getField2()); }
这就是例子的全部,实现Resolver以及调用 Engine 都十分简单。
ARE4j能用在什么地方?
1. 可以使用在任何需要自定义和解析 Annotation 的地方;
2. 可以作为基础的类库用在Annotation驱动的 tool/framework/container。 比如:像Junit4一样的使用annotation的测试框架;像ejb3 jpa这样的容器;以及用来做Permance测试的工具。
参考:
https://github.com/yongyang/are4j
http://scannotation.sourceforge.net
https://github.com/jbossas/jandex
附件是ARE4j的讲解PPT,欢迎查看。