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

  • 相关阅读:
    欧拉回路 定理
    UESTC 1087 【二分查找】
    POJ 3159 【朴素的差分约束】
    ZOJ 1232 【灵活运用FLOYD】 【图DP】
    POJ 3013 【需要一点点思维...】【乘法分配率】
    POJ 2502 【思维是朴素的最短路 卡输入和建图】
    POJ 2240 【这题貌似可以直接FLOYD 屌丝用SPFA通过枚举找正权值环 顺便学了下map】
    POJ 1860【求解是否存在权值为正的环 屌丝做的第一道权值需要计算的题 想喊一声SPFA万岁】
    POJ 1797 【一种叫做最大生成树的很有趣的贪心】【也可以用dij的变形思想~】
    js 实现slider封装
  • 原文地址:https://www.cnblogs.com/LQBlog/p/14208046.html
Copyright © 2011-2022 走看看