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

SpringBoot Maven 插件开发-ASM字节码插桩技术修改代码

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

SpringBoot Maven 插件开发-ASM字节码插桩技术修改代码

需求背景

因业务需要,公司将某项目改造,故需要将业务逻辑层service实现类中所有的私有private方法改为public,以便在项目打包成jar包后,供子类复用父类的私有方法。考虑到业务类比较多,手动改比较麻烦,现采用ASM字节码操作技术编写maven插件,利用插件在项目编译compile阶段进行修改。

maven 插件开发 新建插件项目

1、将项目的pom文件打包方式配置为如下:

maven-plugin

2、新增maven依赖

	
        3.5.2
        2.2.1
        9.0
        5.8.0
        3.5.2
    

    
        
            org.apache.maven
            maven-plugin-api
            ${maven-plugin-api.version}
        
        
            org.apache.maven.plugin-tools
            maven-plugin-annotations
            ${maven-plugin-annotations.version}
            provided
        
        
            org.apache.maven
            maven-project
            ${maven-project.version}
        
        
            org.ow2.asm
            asm
            ${asm.version}
        
        
            cn.hutool
            hutool-all
            ${hutool-all.version}
        
    

3、打包plugin引入如下

	
        
            
                org.apache.maven.plugins
                maven-plugin-plugin
                3.5
            
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.1
                
                    1.8
                    1.8
                    UTF-8
                
            
        
    

4、插件代码开发

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;


@Mojo(name = "modify", defaultPhase = LifecyclePhase.COMPILE)
public class PluginAware extends AbstractMojo {

   // 入参输出目录,${project.build.directory} 表示采用maven的默认配置,为项目下的target目录
   @Parameter(name = "output", defaultValue = "${project.build.directory}")
   private File output;

   public void execute() {
       File f = output;
       if (!f.exists()) {
           f.mkdirs();
       }
       try {
           insertPile(f);
       } catch (Exception e) {
           e.printStackTrace();
       }
   }

   private void insertPile(File root) throws IOException {
       if (root.isDirectory()) {
           for (File file : root.listFiles()) {
               insertPile(file);
           }
       }
       String className = root.getName();
       if (filter(className)) {
           FileOutputStream fos = null;
           try {
               final byte[] data = doInsertPile(root);
               fos = new FileOutputStream(root);
               fos.write(data);
               fos.flush();
           } catch (Exception e) {
               e.printStackTrace();
           } finally {
               if (fos != null) {
                   fos.close();
               }
           }
       }
   }

   private byte[] doInsertPile(File file) {
       try {
           ClassReader cr = new ClassReader(new FileInputStream(file));
           ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
           cr.accept(new MethodClassVisitor(cw), ClassReader.SKIP_DEBUG);
           return cw.toByteArray();
       } catch (Exception e) {
           e.printStackTrace();
           return new byte[0];
       }
   }

   
   private boolean filter(String className) {
       String suffix = "ServiceImpl";
       return className.contains(suffix) && className.length() > suffix.length();
   }
}

import cn.hutool.core.util.StrUtil;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;

public class MethodClassVisitor extends ClassVisitor {

    
    private static final String CONSTRUCTOR = "";


    public MethodClassVisitor(ClassVisitor classVisitor) {
        super(Opcodes.ASM9, classVisitor);
    }

    
    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        // 过滤掉构造器方法
        if (StrUtil.equals(name, CONSTRUCTOR)) {
            return super.visitMethod(access, name, descriptor, signature, exceptions);
        }
        if (access == ACC_PRIVATE) {
            access = ACC_PUBLIC;
        }
        return super.visitMethod(access, name, descriptor, signature, exceptions);
    }
}
使用插件

1、将插件打包安装到本地
切换到项目根目录,执行

mvn clean install

2、在项目中引入已打包好的插件

	
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                {输入你项目的插件版本}
                
                    8
                    8
                    utf8
                
            
            
            
                com.xxxx.framework.plugin
                method-modify-plugin
                1.0-SNAPSHOT
                
                    
                        
                            
                            modify
                        
                        
                        compile
                    
                
            
        
    

相关文章参考连接
ASM字节码插桩技术参考1
ASM字节码插桩技术参考2
maven 内置变量说明参考
maven插件开发参考

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

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

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