栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

编写一个编译时注解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

编写一个编译时注解

最近在回看Java核心技术看到了编译时注解生成Java类并编译,手动尝试了一下 这里模仿ButterKnife写个简单的Dome记录一下,再开安卓项目比较麻烦,这里直接以字符串赋值为例 编写对应注解
@Retention(RetentionPolicy.SOURCE)//保留到源码即可
@Target(ElementType.FIELD)
public @interface Value {
    String value() default "";
}
编写对应处理器
@SupportedAnnotationTypes("com.sk.annotations.Value")//支持的注解
@SupportedSourceVersion(SourceVersion.RELEASE_8)//支持的Java版本
public class ValueProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set annotations, RoundEnvironment roundEnv) {
        Map> map = getFieldMap(annotations, roundEnv);
        createClassFiles(map);
        return true;//返回是否处理完毕 若处理完毕不再需要其他注解处理器处理
    }
    private void createClassFiles(Map> map) {
        for (TypeElement element : map.keySet()) {
            createClassFile(element, map.get(element));
        }
    }
    //生成对应的类文件  这里可以考虑使用模板引擎生成
    private void createClassFile(TypeElement element, List fieldInfos) {
        Messager messager = processingEnv.getMessager();
        String fullName = element.getQualifiedName().toString();
        int index = fullName.lastIndexOf('.');
        String packageName = fullName.substring(0, index);
        String name = fullName.substring(index + 1);
        String className = "Bind_" + name;
        try {
            JavaFileObject file = processingEnv.getFiler().createSourceFile(packageName + "." + className);
            Writer writer = file.openWriter();
            writer.write("package " + packageName + ";n" +
                    "n" +
                    "import com.sk.interfaces.ValueSetter;n" +
                    "n" +
                    "public class " + className + " implements ValueSetter<" + name + "> {n" +
                    "n" +
                    "    @Overriden" +
                    "    public void applyObject(" + name + " target) {n");
            for (FieldInfo fieldInfo : fieldInfos) {
                writer.write("nntarget." + fieldInfo.getName() + "="" + fieldInfo.getValue() + "";n");
            }
            writer.write("    }n" +
                    "n" +
                    "}");
            writer.close();
            messager.printMessage(Diagnostic.Kind.NOTE, "成功生成:" + fullName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private Map> getFieldMap(Set annotations,
                                                          RoundEnvironment roundEnv) {
//        Messager messager = processingEnv.getMessager();
        Map> map = new HashMap<>();
        for (TypeElement annotation : annotations) {//根据注解获取对应元素
            Set elements = roundEnv.getElementsAnnotatedWith(annotation);
            for (Element element : elements) {//处理每个注解元素
                Value value = element.getAnnotation(Value.class);
                TypeElement clazz = (TypeElement) element.getEnclosingElement();
                String name = element.getSimpleName().toString();
                if (!map.containsKey(clazz)) map.put(clazz, new ArrayList<>());
                map.get(clazz).add(new FieldInfo(name, value.value()));
            }
        }
        return map;
    }
}
对应启动类
public class BindTool {
    public static void bind(Object object){
        Class clazz = object.getClass();
        String fullName = clazz.getName();
        int index = fullName.lastIndexOf('.');
        try {//根据类名找对应的绑定类进行绑定
            Class bindClass = (Class) Class.forName(fullName.substring(0, index) + ".Bind_"
                    + fullName.substring(index + 1));
            ValueSetter valueSetter = bindClass.newInstance();
            valueSetter.applyObject(object);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

一些工具类省略了,最后会放上测试项目地址

配置注解处理器

配置Maven不注解处理该项目防止死循环

        
            
                maven-compiler-plugin
                3.8.0
                
                    1.8
                    1.8
                    
                    -proc:none
                
            
        
    
测试结果


这里实际是在编译时生成新的类并编译,并不是像lombok一样直接修改源文件

Dome地址:https://gitee.com/shaokang123/annotation-test

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/343002.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号