zoukankan      html  css  js  c++  java
  • javac AbstractProcessor

    说明

    Annotation Processor是javac的一个工具,它用来在编译时扫描和处理注解,通过Annotation Processor可以获取到注解和被注解类的相关信息,然后根据注解自动生成Java代码,省去了手动编写,提高了编码效率。

    它可以做什么

    在编译的时候动态生成类或者改变类的代码!如:

    lomock:减少get 和set方法的模板代码生成

    mapstruct: 动态生成po vo 互转的Convert类

    hibernate-jpamodelge 动态生成PO类的元数据映射,减少操作字段的模板代码

    需求

    公司内部自己实现了一套基于redis 的CRUD的ORM框架

         //保存活动信息
            BookingActivitySettingRo bookingActivitySettingRo=new BookingActivitySettingRo();
            bookingActivitySettingRo.setId(1L);
            bookingActivitySettingRo.setActivityName("哈哈哈");
            bookingActivitySettingRedisDao.save(bookingActivitySettingRo);
            //查询
            bookingActivitySettingRedisDao.findOne(1L);
            //批量查询
            bookingActivitySettingRedisDao.findByIds(Arrays.asList(1l,2l));
            //删除
            bookingActivitySettingRedisDao.delete(bookingActivitySettingRo.getId());
            //编辑
            BookingActivitySettingRo settingRedisDaoOne= bookingActivitySettingRedisDao.findOne(1L);
            settingRedisDaoOne.setActivityName("我是修改名字");
            bookingActivitySettingRedisDao.save(settingRedisDaoOne);

    为了解决以下问题 

    针对并发场景只操作RO部分字段,优化以下场景的写法导致魔法值过多不易维护问题
    1.并发编辑操作,只操作指定字段,避免整个ro回填,覆盖了其他线程修改的值
    2.并发查询操作,追求性能,RO字段过多,只查询关心部分字段 hmget
    基础工程redis版本1.3.0-SNAPSHO,增加了编译时自动生成映射类

     

    自定义Processor

    参考了hibernate-jpamodelge的实现

    1.实现自定义Processor继承AbstractProcessor重写process方法

    /**
     * @Project 商品uaa
     * @PackageName cn.wine.ms.common.gennerator
     * @ClassName RedisRoAbstractProcessor
     * @Author qiang.li
     * @Date 2020/12/28 1:13 下午
     * @Description 用于编译时针对打了RO注解的类 生成key的映射,优化hset等redis操作部分字段写魔法值的问题
     */
    @SupportedAnnotationTypes({"cn.wine.base.redis.annotation.Ro"})//你的注解的全名称
    @SupportedSourceVersion(SourceVersion.RELEASE_8)//jdk环境为java8
    public class RedisRoProcessor extends AbstractProcessor {
        /**
         * {@inheritDoc}
         * @param annotations
         * @param roundEnvironment
         */
        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
            //遍历所有打了注解的类
            if (!roundEnvironment.processingOver() && annotations.size() != 0) {
                Set<? extends Element> elements = roundEnvironment.getRootElements();
                Iterator var4 = elements.iterator();
                while (var4.hasNext()) {
                    Element element = (Element) var4.next();
                    //只处理打了RO注解的类
                    if (this.isRoEntity(element)) {
                        try {
                            createClass(element);
                        }catch (Exception e){
                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,e.getMessage());
                        }
                    }
                }
            }
            return true;
        }
        /**
         * 创建class文件
         * @param element
         * @throws IOException
         */
        public void createClass(Element element) throws IOException {
            //获得full类名
            String className=(((TypeElement)element).getQualifiedName()).toString();
            //获得包名
            String metaModelPackage=className.substring(0,className.lastIndexOf("."));
            //获得属性元数据
            List<? extends Element> fieldsOfClass = ElementFilter.fieldsIn(element.getEnclosedElements());
            //生成classBody
            String classBody=generateClassBody(fieldsOfClass);
            //用户截取原始类名的startIndex
            Integer index=className.lastIndexOf(".")+1;
            //获得class名字
            String simpleClassName=className.substring(index,className.length());
            //新类的className
            String newClassName=String.format("%s_",simpleClassName);
            //根据名字创建class文件
            createFile(newClassName,metaModelPackage,classBody);
        }
        public void  createFile(String genarateClassName,String metaModelPackage,String body) throws IOException {
            //生成包名
            String generatePackageName = metaModelPackage;
            //创建Java 文件
            JavaFileObject f =processingEnv.getFiler().createSourceFile(genarateClassName);
            try(Writer w = f.openWriter();){
                PrintWriter pw = new PrintWriter(w);
                pw.println("package " + generatePackageName + ";");
                pw.println("
    public class " + genarateClassName + " { ");
                pw.println(body);
                pw.println("    }");
                pw.flush();
            }
        }
    
        /**
         * 构建class内容
         * @param fieldsOfClass
         * @return
         */
        public String  generateClassBody(List<? extends Element> fieldsOfClass){
            StringBuilder body=new StringBuilder();
            for(Element element:fieldsOfClass){
                body.append(String.format("    public final static String %s="%s";",element.getSimpleName(),element.getSimpleName()));
                body.append("
    
    ");
            }
            return body.toString();
        }
    
        /**
         * 是否是打了RO注解的Entity
         * @param element
         * @return
         */
        private boolean isRoEntity(Element element) {
            return containsAnnotation(element, new String[]{"cn.wine.base.redis.annotation.Ro"});
        }
    
        /**
         * 是否有打了指定注解
         * @param element
         * @return
         */
        public static boolean containsAnnotation(Element element, String... annotations) {
            assert element != null;
    
            assert annotations != null;
    
            List<String> annotationClassNames = new ArrayList();
            Collections.addAll(annotationClassNames, annotations);
            List<? extends AnnotationMirror> annotationMirrors = element.getAnnotationMirrors();
            Iterator var4 = annotationMirrors.iterator();
    
            AnnotationMirror mirror;
            do {
                if (!var4.hasNext()) {
                    return false;
                }
    
                mirror = (AnnotationMirror)var4.next();
            } while(!annotationClassNames.contains(mirror.getAnnotationType().toString()));
    
            return true;
        }
    }

    2.在resource下新增META-INF/services并创建文件javax.annotation.processing.Processor 

    将自定义的processor的全名称配置进去

    #注:如果搭配jpa和mapstract或者lomack的processr冲突 通过以下类似配置解决
    # <plugin>
     #                <groupId>org.apache.maven.plugins</groupId>
     #                <artifactId>maven-compiler-plugin</artifactId>
     #                <version>3.7.0</version>
     #                <configuration>
     #                    <source>${java.version}</source>
     #                    <target>${java.version}</target>
     #                    <annotationProcessorPaths>
     #                        <path>
     #                            <groupId>org.projectlombok</groupId>
     #                            <artifactId>lombok</artifactId>
     #                            <version>${lombok.version}</version>
     #                        </path>
     #                        <path>
     #                            <groupId>org.mapstruct</groupId>
     #                            <artifactId>mapstruct-processor</artifactId>
     #                            <version>1.2.0.Final</version>
     #                        </path>
     #                        <path>
     #                            <groupId>org.hibernate</groupId>
     #                            <artifactId>hibernate-jpamodelgen</artifactId>
     #                            <version>5.2.17.final</version>
     #                        </path>
     #                    </annotationProcessorPaths>
     #                </configuration>
     #            </plugin>
    #
    cn.wine.base.redis.gennerator.RedisRoProcessor

     

     然后在其他使用的地方引入这个jar就行了

    与其他Processor使用冲突解决

          <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-compiler-plugin</artifactId>
                                <version>3.7.0</version>
                                <configuration>
                                    <source>${java.version}</source>
                                    <target>${java.version}</target>
                                    <annotationProcessorPaths>
                                        <path>
                                            <groupId>org.projectlombok</groupId>
                                            <artifactId>lombok</artifactId>
                                            <version>${lombok.version}</version>
                                        </path>
                                        <path>
                                            <groupId>org.mapstruct</groupId>
                                            <artifactId>mapstruct-processor</artifactId>
                                            <version>1.2.0.Final</version>
                                        </path>
                                        <path>
                                            <groupId>org.hibernate</groupId>
                                            <artifactId>hibernate-jpamodelgen</artifactId>
                                            <version>5.2.17.final</version>
                                        </path>
                                        <path>
                                            <groupId>cn.wine</groupId>
                                            <artifactId>support-redis</artifactId>
                                            <version>${support-redis.version}</version>
                                        </path>
                                    </annotationProcessorPaths>
                                </configuration>
                            </plugin>

    如何调试

    1.新建一个remote

     2.指定mvnDebugger

  • 相关阅读:
    成绩等级
    函数值
    最大数
    温度转换
    何时使用hadoop fs、hadoop dfs与hdfs dfs命令
    Hadoop常见异常及其解决方案
    Hadoop2.4.1入门实例:MaxTemperature
    单机/伪分布式Hadoop2.4.1安装文档
    用Apache Ivy实现项目里的依赖管理
    【Nutch2.2.1基础教程之2.1】集成Nutch/Hbase/Solr构建搜索引擎之一:安装及运行【单机环境】
  • 原文地址:https://www.cnblogs.com/LQBlog/p/14208046.html
Copyright © 2011-2022 走看看