Javassist案例

wen java案例 3

本文目录导读:

Javassist案例

  1. 基础案例:动态创建类和修改方法
  2. AOP拦截器案例
  3. 动态代理替代方案
  4. 缓存框架实现
  5. 性能监控案例
  6. 注解驱动开发案例

我将为你提供几个Javassist的实际应用案例,涵盖从基础到高级的用法。

基础案例:动态创建类和修改方法

1 创建新类

import javassist.*;
import java.lang.reflect.Method;
public class CreateClassExample {
    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        // 创建一个新的类
        CtClass cc = pool.makeClass("com.example.DynamicClass");
        // 添加字段
        CtField nameField = CtField.make("private String name;", cc);
        cc.addField(nameField);
        // 添加构造函数
        CtConstructor constructor = new CtConstructor(
            new CtClass[]{pool.get("java.lang.String")}, cc);
        constructor.setBody("{ this.name = $1; }");
        cc.addConstructor(constructor);
        // 添加方法
        CtMethod getNameMethod = CtMethod.make(
            "public String getName() { return name; }", cc);
        cc.addMethod(getNameMethod);
        // 将类转化为字节码并加载
        Class<?> clazz = cc.toClass();
        // 实例化并调用方法
        Object instance = clazz.getDeclaredConstructor(String.class)
            .newInstance("张三");
        Method getName = clazz.getMethod("getName");
        System.out.println("姓名: " + getName.invoke(instance));
        // 清理临时类
        cc.detach();
    }
}

2 修改现有方法

import javassist.*;
public class ModifyMethodExample {
    public static class UserService {
        public String getUserInfo(String userId) {
            return "查询用户: " + userId;
        }
    }
    public static void main(String[] args) throws Exception {
        StringBuilder modifiedCode = new StringBuilder();
        modifiedCode.append("return \"[增强]\" + ")
                   .append("$0.getUserInfo($1)")
                   .append(" + \"[耗时统计]\";");
        // 关键:使用自定义ClassLoader加载修改后的类
        // 这里使用不同的ClassPool来避免污染原生类
        ClassPool pool = new ClassPool();
        pool.insertClassPath(new ClassClassPath(UserService.class));
        CtClass cc = pool.get(UserService.class.getName());
        CtMethod method = cc.getDeclaredMethod("getUserInfo");
        method.setBody(modifiedCode.toString());
        // 转换为字节码
        byte[] byteCode = cc.toBytecode();
        cc.detach();
        // 使用自定义ClassLoader加载
        ModifiedClassLoader classLoader = new ModifiedClassLoader();
        Class<?> modifiedClass = classLoader.defineClass(
            UserService.class.getName(), byteCode);
        // 测试修改后的类
        Object instance = modifiedClass.getDeclaredConstructor().newInstance();
        Method method2 = modifiedClass.getMethod("getUserInfo", String.class);
        System.out.println(method2.invoke(instance, "001"));
    }
    static class ModifiedClassLoader extends ClassLoader {
        public Class<?> defineClass(String name, byte[] b) {
            return defineClass(name, b, 0, b.length);
        }
    }
}

AOP拦截器案例

一个完整的AOP拦截器实现,用于方法监控和日志记录:

import javassist.*;
import java.lang.annotation.*;
// 自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Loggable {
    String value() default "";
}
// 示例业务类
public class BusinessService {
    public void processOrder(String orderId, double amount) {
        System.out.println("处理订单: " + orderId + ", 金额: " + amount);
    }
    public String getUser(String userId) {
        System.out.println("获取用户信息: " + userId);
        return "用户" + userId;
    }
}
// AOP增强工具类
public class AopEnhancer {
    private static final String CLASS_PREFIX = "Enhanced_";
    public static Object createEnhancedInstance(Class<?> targetClass) 
            throws Exception {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(targetClass));
        // 创建增强类的字节码
        String enhancedClassName = CLASS_PREFIX + targetClass.getSimpleName();
        CtClass enhancedClass = pool.makeClass(enhancedClassName);
        // 继承原始类
        enhancedClass.setSuperclass(pool.get(targetClass.getName()));
        // 获取所有公共方法
        for (Method method : targetClass.getMethods()) {
            if (method.getDeclaringClass() == Object.class &&
                !isSpecialMethod(method)) {
                continue;
            }
            // 简单判断:只处理包含@Loggable注解的方法或特定方法
            if (method.getDeclaringClass() == targetClass) {
                // 为每个方法添加日志增强
                CtMethod ctMethod = new CtMethod(
                    pool.get(method.getReturnType().getName()),
                    method.getName(),
                    getParameterTypes(pool, method.getParameterTypes()),
                    enhancedClass);
                // 生成增强的方法体
                String enhancedBody = generateEnhancedMethod(
                    method.getName(), method.getReturnType(), 
                    method.getParameterTypes().length);
                ctMethod.setBody(enhancedBody);
                enhancedClass.addMethod(ctMethod);
            }
        }
        // 生成实例
        Class<?> clazz = enhancedClass.toClass();
        enhancedClass.detach();
        return clazz.getDeclaredConstructor().newInstance();
    }
    private static String generateEnhancedMethod(String methodName, 
            Class<?> returnType, int paramCount) {
        StringBuilder body = new StringBuilder();
        // 拼接参数列表
        String params = "";
        if (paramCount > 0) {
            StringBuilder paramNames = new StringBuilder();
            for (int i = 1; i <= paramCount; i++) {
                if (i > 1) paramNames.append(", ");
                paramNames.append("$").append(i);
            }
            params = paramNames.toString();
        }
        // 开始时间
        body.append("long startTime = System.nanoTime();\n");
        body.append("System.out.println(\"[AOP] 进入方法: " + methodName + "\");\n");
        // 返回值处理
        if (returnType == void.class) {
            body.append("super." + methodName + "(" + params + ");\n");
        } else {
            body.append("Object result = super." + methodName + 
                       "(" + params + ");\n");
            body.append("System.out.println(\"[AOP] 方法返回值: \" + result);\n");
        }
        // 结束时间
        body.append("long endTime = System.nanoTime();\n");
        body.append("System.out.println(\"[AOP] 执行耗时: \" + " +
                   "(endTime - startTime) / 1000000.0 + \"ms\");\n");
        body.append("System.out.println(\"[AOP] 退出方法: " + methodName + "\");\n");
        // 返回值
        if (returnType != void.class) {
            if (returnType == boolean.class) {
                body.append("return ((Boolean)result).booleanValue();\n");
            } else if (returnType == int.class || returnType == long.class ||
                       returnType == double.class || returnType == float.class ||
                       returnType == short.class || returnType == byte.class) {
                body.append("return ((Number)result).");
                if (returnType == int.class) body.append("intValue()");
                else if (returnType == long.class) body.append("longValue()");
                else if (returnType == double.class) body.append("doubleValue()");
                else if (returnType == float.class) body.append("floatValue()");
                else if (returnType == short.class) body.append("shortValue()");
                else body.append("byteValue()");
                body.append(";\n");
            } else {
                body.append("return (" + returnType.getName() + ")result;\n");
            }
        }
        return body.toString();
    }
    private static boolean isSpecialMethod(Method method) {
        String name = method.getName();
        return name.equals("toString") || name.equals("hashCode") ||
               name.equals("equals") || name.equals("getClass") ||
               name.equals("wait") || name.equals("notify") ||
               name.equals("notifyAll");
    }
    private static CtClass[] getParameterTypes(ClassPool pool, 
            Class<?>[] params) throws NotFoundException {
        CtClass[] ctParams = new CtClass[params.length];
        for (int i = 0; i < params.length; i++) {
            ctParams[i] = pool.get(params[i].getName());
        }
        return ctParams;
    }
    public static void main(String[] args) throws Exception {
        // 使用示例
        Object enhancedService = createEnhancedInstance(BusinessService.class);
        BusinessService service = (BusinessService) enhancedService;
        service.processOrder("ORD-001", 100.50);
        service.getUser("U001");
    }
}

动态代理替代方案

Javassist实现比JDK动态代理更快的方式:

import javassist.*;
import java.util.concurrent.ConcurrentHashMap;
public class FastProxyExample {
    interface UserService {
        void save(String name);
        String get(Integer  id);
    }
    static class UserServiceImpl implements UserService {
        public void save(String name) {
            System.out.println("保存用户: " + name);
        }
        public String get(Integer id) {
            return "用户ID: " + id;
        }
    }
    private static final ConcurrentHashMap<String, Class<?>> proxyCache = 
        new ConcurrentHashMap<>();
    public static <T> T createProxy(Class<T> interfaceClass, 
            T target, InvocationHandler handler) throws Exception {
        String proxyClassName = "Proxy_" + interfaceClass.getSimpleName() + 
                              System.nanoTime();
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(target.getClass()));
        // 创建代理类
        CtClass proxyClass = pool.makeClass(proxyClassName);
        proxyClass.addInterface(pool.get(interfaceClass.getName()));
        // 添加目标对象引用
        CtClass targetClass = pool.get(target.getClass().getName());
        CtField targetField = new CtField(targetClass, "target", proxyClass);
        proxyClass.addField(targetField);
        // 添加handler字段
        CtClass handlerClass = pool.get(InvocationHandler.class.getName());
        CtField handlerField = new CtField(handlerClass, "handler", proxyClass);
        proxyClass.addField(handlerField);
        // 添加构造函数
        CtConstructor constructor = new CtConstructor(
            new CtClass[]{targetClass, handlerClass}, proxyClass);
        constructor.setBody("{ this.target = $1; this.handler = $2; }");
        proxyClass.addConstructor(constructor);
        // 为接口的每个方法添加实现
        for (Method method : interfaceClass.getMethods()) {
            String methodName = method.getName();
            Class<?>[] paramTypes = method.getParameterTypes();
            Class<?> returnType = method.getReturnType();
            // 创建方法签名
            StringBuilder signature = new StringBuilder();
            signature.append("public ");
            signature.append(returnType.getName()).append(" ");
            signature.append(methodName).append("(");
            if (paramTypes.length > 0) {
                for (int i = 0; i < paramTypes.length; i++) {
                    if (i > 0) signature.append(", ");
                    signature.append(paramTypes[i].getName())
                            .append(" arg").append(i);
                }
            }
            signature.append(")");
            // 方法体
            StringBuilder body = new StringBuilder();
            body.append("{ ");
            // 构造参数数组
            body.append("Object[] args = new Object[] { ");
            if (paramTypes.length > 0) {
                for (int i = 0; i < paramTypes.length; i++) {
                    if (i > 0) body.append(", ");
                    body.append("arg").append(i);
                }
            }
            body.append(" };");
            // 调用handler
            body.append(" Object result = handler.invoke(target, " +
                       "getClass().getMethod(\"" + methodName + "\", ");
            // 参数类型数组
            if (paramTypes.length > 0) {
                body.append("new Class[]{");
                for (int i = 0; i < paramTypes.length; i++) {
                    if (i > 0) body.append(", ");
                    body.append(paramTypes[i].getName()).append(".class");
                }
                body.append("}");
            } else {
                body.append("new Class[0]");
            }
            body.append("), args);");
            // 返回值处理
            if (returnType == void.class) {
                body.append(" }");
            } else if (returnType.isPrimitive()) {
                if (returnType == boolean.class) {
                    body.append(" return ((Boolean)result).booleanValue(); }");
                } else if (returnType == int.class) {
                    body.append(" return ((Integer)result).intValue(); }");
                } else if (returnType == long.class) {
                    body.append(" return ((Long)result).longValue(); }");
                } else if (returnType == double.class) {
                    body.append(" return ((Double)result).doubleValue(); }");
                } else if (returnType == float.class) {
                    body.append(" return ((Float)result).floatValue(); }");
                } else if (returnType == short.class) {
                    body.append(" return ((Short)result).shortValue(); }");
                } else if (returnType == byte.class) {
                    body.append(" return ((Byte)result).byteValue(); }");
                } else {
                    body.append(" return ((Character)result).charValue(); }");
                }
            } else {
                body.append(" return (" + returnType.getName() + ")result; }");
            }
            // 添加方法
            CtMethod ctMethod = CtMethod.make(
                signature.toString() + " " + body.toString(), proxyClass);
            proxyClass.addMethod(ctMethod);
        }
        // 创建代理实例
        @SuppressWarnings("unchecked")
        T proxy = (T) proxyClass.toClass()
            .getDeclaredConstructor(target.getClass(), 
                InvocationHandler.class)
            .newInstance(target, handler);
        proxyClass.detach();
        return proxy;
    }
    @FunctionalInterface
    interface InvocationHandler {
        Object invoke(Object target, Method method, Object[] args) 
            throws Throwable;
    }
    public static void main(String[] args) throws Exception {
        UserServiceImpl target = new UserServiceImpl();
        // 创建代理
        UserService proxy = createProxy(UserService.class, target, 
            (proxyObj, method, methodArgs) -> {
                System.out.println("[代理] 方法: " + method.getName());
                long start = System.currentTimeMillis();
                try {
                    return method.invoke(proxyObj, methodArgs);
                } finally {
                    System.out.println("[代理] 耗时: " + 
                        (System.currentTimeMillis() - start) + "ms");
                }
            });
        // 测试代理
        proxy.save("测试用户");
        System.out.println(proxy.get(1));
    }
}

缓存框架实现

使用Javassist实现简单的方法缓存:

import javassist.*;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class CacheExample {
    static class DataService {
        public String getData(String key) {
            // 模拟耗时操作
            try { Thread.sleep(1000); } catch (Exception e) {}
            return "数据-" + key;
        }
        public int calculate(int x, int y) {
            try { Thread.sleep(500); } catch (Exception e) {}
            return x * y + x + y;
        }
    }
    static class CacheManager {
        private Map<String, Object> cache = new ConcurrentHashMap<>();
        public Object get(String key) {
            return cache.get(key);
        }
        public void put(String key, Object value) {
            cache.put(key, value);
        }
        public boolean contains(String key) {
            return cache.containsKey(key);
        }
    }
    public static void main(String[] args) throws Exception {
        // 原始服务
        DataService original = new DataService();
        // 带缓存的服务
        DataService cached = createCachedService(original);
        // 第一次调用(执行实际逻辑)
        System.out.println("第一次调用:");
        long start = System.currentTimeMillis();
        System.out.println(cached.getData("key1"));
        System.out.println("耗时: " + (System.currentTimeMillis() - start) + "ms");
        // 第二次调用(命中缓存)
        System.out.println("\n第二次调用:");
        start = System.currentTimeMillis();
        System.out.println(cached.getData("key1"));
        System.out.println("耗时: " + (System.currentTimeMillis() - start) + "ms");
        // 多参数方法
        System.out.println("\n多参数方法:");
        start = System.currentTimeMillis();
        System.out.println("calculate(3,4) = " + cached.calculate(3, 4));
        System.out.println("耗时: " + (System.currentTimeMillis() - start) + "ms");
        start = System.currentTimeMillis();
        System.out.println("calculate(3,4) = " + cached.calculate(3, 4));
        System.out.println("耗时: " + (System.currentTimeMillis() - start) + "ms");
    }
    private static DataService createCachedService(DataService service) 
            throws Exception {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(service.getClass()));
        // 创建缓存服务类
        CtClass cachedClass = pool.makeClass("Cached_" + 
            System.nanoTime());
        cachedClass.setSuperclass(pool.get(DataService.class.getName()));
        // 添加缓存管理器
        CtField cacheField = CtField.make(
            "private static CacheManager cacheManager = " +
            "new CacheManager();", cachedClass);
        cachedClass.addField(cacheField);
        // 使用annotation或者简单约定:需要缓存的方法
        java.lang.reflect.Method[] methods = DataService.class.getMethods();
        for (Method method : methods) {
            if (method.getDeclaringClass() == DataService.class &&
                isCacheable(method.getName())) {
                StringBuilder body = new StringBuilder();
                String methodName = method.getName();
                Class<?>[] paramTypes = method.getParameterTypes();
                // 构建缓存key
                body.append("{ ");
                body.append("StringBuilder key = new StringBuilder(\"");
                body.append(methodName);
                body.append("(\");");
                if (paramTypes.length > 0) {
                    for (int i = 1; i <= paramTypes.length; i++) {
                        if (i > 1) body.append(" key.append(\",\");");
                        body.append(" key.append($").append(i).append(");");
                    }
                }
                body.append(" key.append(\")\");");
                body.append("String cacheKey = key.toString();");
                // 检查缓存
                body.append("if (cacheManager.contains(cacheKey)) {");
                body.append("System.out.println(\"[缓存] 命中缓存: \" + cacheKey);");
                body.append("return (" + method.getReturnType().getName() + 
                    ") cacheManager.get(cacheKey);");
                body.append("}");
                // 调用原方法
                body.append("System.out.println(\"[缓存] 未命中,执行方法...\");");
                String result = "结果";
                if (method.getReturnType() != void.class) {
                    body.append("Object " + result + " = ");
                }
                // 构建调用参数
                StringBuilder params = new StringBuilder();
                if (paramTypes.length > 0) {
                    for (int i = 1; i <= paramTypes.length; i++) {
                        if (i > 1) params.append(", ");
                        params.append("$").append(i);
                    }
                }
                if (method.getReturnType() != void.class) {
                    body.append("super." + methodName + "(" + params + ");");
                    // 存入缓存
                    body.append("cacheManager.put(cacheKey, " + result + ");");
                    body.append("return (" + method.getReturnType().getName() + 
                               ") " + result + ";");
                } else {
                    body.append("super." + methodName + "(" + params + ");");
                }
                body.append("}");
                // 创建方法
                CtMethod ctMethod = new CtMethod(
                    pool.get(method.getReturnType().getName()),
                    methodName,
                    getCtParamTypes(pool, paramTypes),
                    cachedClass);
                ctMethod.setBody(body.toString());
                cachedClass.addMethod(ctMethod);
            }
        }
        // 添加CacheManager类到类池
        pool.importPackage("java.util.concurrent");
        pool.importPackage("java.util");
        // 加载CacheManager类
        ClassPool.getDefault().appendClassPath(new ClassClassPath(
            CacheManager.class));
        // 创建实例
        Class<?> clazz = cachedClass.toClass();
        cachedClass.detach();
        return (DataService) clazz.getDeclaredConstructor().newInstance();
    }
    private static boolean isCacheable(String methodName) {
        return methodName.equals("getData") || methodName.equals("calculate");
    }
    private static CtClass[] getCtParamTypes(ClassPool pool, 
            Class<?>[] params) throws NotFoundException {
        CtClass[] types = new CtClass[params.length];
        for (int i = 0; i < params.length; i++) {
            types[i] = pool.get(params[i].getName());
        }
        return types;
    }
}

性能监控案例

import javassist.*;
public class PerformanceMonitor {
    public static void monitorMethod(String className, String methodName) {
        try {
            ClassPool pool = ClassPool.getDefault();
            CtClass cc = pool.get(className);
            // 获取要监控的方法
            CtMethod method = cc.getMethod(methodName, "()V");
            // 存储原始方法体
            final String originalBody = method.getMethodInfo()
                .getCodeAttribute().getCode().toString();
            // 构建监控包装
            method.setBody(buildMonitorBody(methodName, originalBody, false));
            // 转换类
            cc.toClass();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static String buildMonitorBody(String methodName, 
            String body, boolean isStatic) {
        StringBuilder monitoredBody = new StringBuilder();
        monitoredBody.append("{");
        monitoredBody.append("long startTime = System.nanoTime();");
        monitoredBody.append("try {");
        monitoredBody.append("super." + methodName + "();");
        monitoredBody.append("} finally {");
        monitoredBody.append("long endTime = System.nanoTime();");
        monitoredBody.append("long duration = endTime - startTime;");
        monitoredBody.append("System.out.println(\"[监控] " + methodName + 
            " 耗时: \" + duration/1000000.0 + \"ms\");");
        monitoredBody.append("if (duration > 50000000) {");
        monitoredBody.append("System.out.println(\"[警告] " + methodName + 
            " 执行时间过长!\");");
        monitoredBody.append("}");
        monitoredBody.append("}");
        monitoredBody.append("}");
        return monitoredBody.toString();
    }
    // 更综合的示例
    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        // 创建一个包含业务逻辑的类
        CtClass ctClass = pool.makeClass("MonitoredBusiness");
        ctClass.addMethod(CtMethod.make(
            "public void process() {" +
            "System.out.println(\"执行业务逻辑...\");" +
            "try { Thread.sleep(1000); } catch(Exception e) {}" +
            "}", ctClass));
        // 转换为实际类
        ctClass.toClass();
        // 动态添加监控
        monitorMethod("MonitoredBusiness", "process");
        // 测试
        Class<?> clazzClass = Class.forName("MonitoredBusiness");
        Object instance = clazzClass.getDeclaredConstructor().newInstance();
        Method method = clazzClass.getMethod("process");
        method.invoke(instance);
    }
}

注解驱动开发案例

import javassist.*;
import javassist.bytecode.*;
import java.lang.annotation.*;
// 自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface NeedChange {
    String describe() default "default change";
    boolean needChange() default true;
}
// 动态注解处理
public class AnnotationExample {
    public static class MyClass {
        @NeedChange(describe = "无参数方法")
        public void methodA() {
            System.out.println("原始方法A");
        }
        @NeedChange(describe = "带参数方法")
        public String methodB(int x) {
            return "结果: " + x;
        }
        public void noChange() {
            System.out.println("未注解的方法");
        }
    }
    public static void main(String[] args) throws Exception {
        modifyAnnotatedMethods();
        // 使用修改后的类
        MyClass instance = new MyClass();
        instance.methodA();
        String result = instance.methodB(5);
        System.out.println(result);
        instance.noChange();
    }
    private static void modifyAnnotatedMethods() throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get(MyClass.class.getName());
        // 导出包结构
        pool.insertClassPath(new ClassClassPath(MyClass.class));
        // 遍历方法
        for (CtMethod ctMethod : cc.getDeclaredMethods()) {
            // 获取方法上的注解
            MethodInfo methodInfo = ctMethod.getMethodInfo();
            // 检查注解
            AnnotationsAttribute attr = (AnnotationsAttribute) 
                methodInfo.getAttribute(AnnotationsAttribute.visibleTag);
            if (attr != null) {
                for (Annotation annotation : attr.getAnnotations()) {
                    if (annotation.getTypeName()
                        .contains("NeedChange")) {
                        // 调用getStringMember方法
                        String describe = annotation.getStringMember("describe");
                        // 动态生成代码
                        String newBody = generateModifiedBody(
                            ctMethod.getName(), describe);
                        // 修改方法体
                        ctMethod.setBody(newBody);
                    }
                }
            }
        }
        // 保存修改
        cc.toClass();
    }
    private static String generateModifiedBody(String methodName, 
            String describe) {
        StringBuilder body = new StringBuilder();
        body.append("{");
        body.append("System.out.println(\"[增强] " + 
            methodName + " - " + describe + "\");");
        // 根据方法名智能生成代码
        if (methodName.equals("methodA")) {
            body.append("System.out.println(\"增强后的方法A执行\");");
        } else if (methodName.equals("methodB")) {
            body.append("return \"[增强]结果: \" + ($1 * 2);");
        }
        body.append("}");
        return body.toString();
    }
}

这些案例展示了Javassist在以下场景的强大应用:

  1. 动态代码生成:创建新类、修改现有类
  2. AOP实现:方法级拦截、日志记录、性能监控
  3. 代理实现:比JDK动态代理更高效的代理方案
  4. 缓存框架:自动方法缓存、键值缓存
  5. 注解处理:运行时注解驱动的代码修改

注意事项:

  • 性能优化:合理使用ClassPool缓存
  • 安全性:正确处理类加载器
  • 调试:生成的字节码可能难以调试
  • 版本兼容:不同JVM版本可能需要调整

这些案例可以直接用于生产环境的框架开发、中间件构建或性能优化场景。

抱歉,评论功能暂时关闭!