字节码增强

638 阅读1分钟

字节码增强案例:

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 增强dubboNetUtils
 * Created by carloszhang
 */
@Slf4j
@Component
public class EnhancedNetUtil implements BeanPostProcessor {

    /**
     * 修改dubbo netutil
     */
    @PostConstruct
    public void enhanceNetUtil() {
        try {
            ClassPool pool = ClassPool.getDefault();
            
            /**
             *
             * Javassist NotFoundException
            */
            ClassClassPath classpath = new ClassClassPath(this.getClass());
            pool.insertClassPath(classpath);
            
            
            CtClass ctClass = pool.get("com.alibaba.dubbo.common.utils.NetUtils");
            CtMethod getLocalAddress0 = ctClass.getDeclaredMethod("getLocalAddress0");
            getLocalAddress0.setBody("return java.net.InetAddress.getByName(com.github.brevy.commons.net.NetUtil.getLocalIP());");
            ctClass.toClass();
        } catch (Exception e) {
            log.error("替换dubbo-NetUtils", e);
        }


    }

    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        return o;
    }
}

javassist官网对此有如下说明:

The default ClassPool returned by a static method ClassPool.getDefault() searches the same path that the underlying JVM (Java virtual machine) has. If a program is running on a web application server such as JBoss and Tomcat, the ClassPoolobject may not be able to find user classes since such a web application server uses multiple class loaders as well as the system class loader. In that case, an additional class path must be registered to the ClassPool.

1.(推荐)

ClassPool pool = ClassPool.getDefault();
   ClassClassPath classPath = new ClassClassPath(this.getClass());
   pool.insertClassPath(classPath);
<dependency>
    <groupId>javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.12.1.GA</version>
</dependency>