java 自定义注解器 Mapper,并提交私仓 maven
1. java 自定义注解器
1.1 注解器作用
通过元注解对类、变量等进行标记,在代码编译期通过解析器 AbstractProcessor
进行解析,快速实现模板代码的构建等作用
1.2 自定义注解
通过 @interface
实现注解,如:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface MapType {
String name() default "";
}
1.3 实现一个解析器 Processor
- 必须继承
AbstractProcessor
,通过方法public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
对定义的注解类型进行解析。 - 需要重写
getSupportedAnnotationTypes()
声明对哪些些注解生效 - 在
init(ProcessingEnvironment processingEnv)
中获取工具类,如:@Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); Types typeUtils = processingEnv.getTypeUtils(); Elements elementUtils = processingEnv.getElementUtils(); Filter filer = processingEnv.getFiler(); Messager messager = processingEnv.getMessager(); }
1.4 解析注解,构建类
从自定义解析器可以获取并处理自定义注解类型,动态构建类可以通过 JavaWriter
或者 JavaPoet
。
JavaPoet
是对 JavaWriter
的进一步封装。
如何使用参考官网介绍:JavaPoet github 链接
2. 实现注解库
新建 java library,建议使用 idea 的 maven/gradle 工程
2.1 mapper-annotation 注解库
新建 java library,命名为 mapper-annotation,用于存放注解。
也可以把注解、解析器等放在同一个库中,但一般解析器所依赖的库只需要在编译期使用,不需要打包进主工程,所以会选择库拆分。
2.2 mapper-compiler 解析库
同样新建 java library,再添加 JavaPoet
依赖,在 module 的 build.gradle 中添加 implementation group: 'com.squareup', name: 'javapoet', version: '1.8.0'
在项目调试阶段,增加注解库依赖 implementation project(":mapper-annotation")
,在调试完成后,可以将直接依赖替换为线上依赖,如 implementation 'com.lib:mapper-annotation:1.0.0'
2.3 mapper aar 库
这个库主要是存放对外访问的接口。给 android 项目使用,如果没有这类需求可以不加,或者也可以放入 annotation 库中,不是必要创建的库。
新建 android library,同样需要添加对 annotation 依赖,在上线后替换为线上版本,如上。
3. 自定义 mapper 注解库需求及实现
3.1 构建需求
在业务项目中使用了大量的组件,在使用中需要根据用户的组件类型去匹配,呈现该组件。在原先开发中,流程如下:
private void showComponent(Item item){
String type = item.getType();
if("A".equals(type){
Component cc = new A(item);
cc.show();
}else if("B".equals(type){
Component cc = new B(item);
cc.show();
}else if("C".equals(type){
Component cc = new C(item);
cc.show();
}else {
//...
}
}
在少量组件的情况下,使用 if-else 结构清晰,但随着项目扩展,这段判断特别长,因此有了第一次改造,修改后如下:
private static HashMap<Strng,Class> map = new HashMap<>();
static{
map.put("A",A.class);
map.put("B",B.class);
map.put("C",C.class);
//...
}
private void showComponent(Item item)