zoukankan      html  css  js  c++  java
  • Javassist 实现代码增强

    /**
     * Desc:TODO
     * 
     * @author zhangwei<wei.zw@corp.netease.com>
     * @since 2016年1月14日 下午9:19:34
     * @version v 0.1
     */
    public final class ClassEnhancedGenerator {
    	
    	private ClassEnhancedGenerator() {
    	}
    
    	/**
    	 * 类方法增强<BR>
    	 *
    	 * 对指定类的方法进行代码增强(将指定的原方法名改为$enhanced,同时复制原方法名进行代码注入)
    	 * 
    	 * @param className
    	 *            待增强的类名
    	 * @param methodName
    	 *            待增强的方法名
    	 * @param provider
    	 *            {@link ClassInjectProvider}实现类
    	 * @throws Exception
    	 */
    	public static void enhancedMethod(Class<?> cls, Method[] methods, InjectType injectType, ClassInjectProvider provider)
    			throws Exception {
    		CtClass ctClass = ClassPool.getDefault().get(cls.getName());
    		for (int i = 0; i < methods.length; i++) {
    			injectCodeForMethod(ctClass, methods[i].getName(), injectType, provider);
    		}
    		String resource = cls.getName().replace(".", "/") + ".class";
    		URI uri = ClassLoader.getSystemClassLoader().getResource(resource).toURI();
    		String classFilePath = uri.getRawPath().substring(0, uri.getRawPath().length() - resource.length());
    		ctClass.writeFile(classFilePath);
    	}
    
    	/***
    	 * 注入增强代码
    	 * 
    	 * @param ctClass
    	 * @param methodName
    	 * @param injectType
    	 * @param provider
    	 * @throws Exception
    	 * @author zhangwei<wei.zw@corp.netease.com>
    	 */
    	private static void injectCodeForMethod(CtClass ctClass, String methodName, InjectType injectType,
    			ClassInjectProvider provider) throws Exception {
    		CtMethod oldMethod = ctClass.getDeclaredMethod(methodName);
    		// 修改原有的方法名称为"方法名$enhanced",如果已存在该方法则返回
    		String originalMethod = methodName + "$enhanced";
    		CtMethod[] methods = ctClass.getMethods();
    		for (int i = 0; i < methods.length; i++) {
    			CtMethod method = methods[i];
    			if (method.getName().equals(originalMethod)) {
    				return;
    			}
    		}
    		oldMethod.setName(originalMethod);
    		// 增加代码,复制原来的方法名作为增强的新方法,同时调用原有方法即"方法名$enhanced"
    		CtMethod enhancedMethod = CtNewMethod.copy(oldMethod, methodName, ctClass, null);
    		// 对复制的方法注入代码
    		StringBuffer methodBody = new StringBuffer();
    		methodBody.append("{");
    		switch (injectType) {
    		case BEFORE:
    			methodBody.append(provider.injectCode(enhancedMethod));
    			methodBody.append("return " + originalMethod + "($$); ");
    			break;
    		case AFTER:
    			methodBody.append("try{");
    			methodBody.append("return " + originalMethod + "($$); ");
    			methodBody.append("}finally{");
    			methodBody.append(provider.injectCode(enhancedMethod));
    			methodBody.append("}");
    			break;
    		default:
    			String injectCode = provider.injectCode(enhancedMethod);
    			methodBody.append(injectCode);
    		}
    		methodBody.append("}");
    		enhancedMethod.setBody(methodBody.toString());
    		ctClass.addMethod(enhancedMethod);
    	}
    }
    
    /**
     * Desc:TODO
     * 
     * @author zhangwei<wei.zw@corp.netease.com>
     * @since 2016年1月14日 下午9:21:51
     * @version v 0.1
     */
    public interface ClassInjectProvider {
    
    	/**
    	 * 对指定的方法注入代码
    	 *
    	 * @param ctMethod
    	 *            CtMethod
    	 * @return
    	 */
    	public String injectCode(final CtMethod ctMethod) throws Exception;
    
    }
    
    /**
     * Desc:TODO
     * 
     * @author zhangwei<wei.zw@corp.netease.com>
     * @since 2016年1月14日 下午9:23:17
     * @version v 0.1
     */
    public enum InjectType {
    	BEFORE, AFTER, REPLACE;
    }
    
  • 相关阅读:
    Java的内存结构(Memory Structure)和垃圾收集(Garbage Collection)图解
    走遍天下的三大vb控制结构
    程序员快速阅读,绝对不是神话
    Android4.0.3源码分析——开机流程之Zygote
    云端的天使
    提高班的“伞”
    Android 4.0.3 源代码结构分析(一)
    如何在Java中选择Map/List/Set
    关于Hadoop中reducer端combiner的一些思考
    vb添加GIF动态图片
  • 原文地址:https://www.cnblogs.com/wei-zw/p/8797743.html
Copyright © 2011-2022 走看看