`
i_coding
  • 浏览: 15465 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

javassit实现动态代理解决代理必须要接口的缺憾

阅读更多
/**
* 接口随着代理目标自动生成 (背景:一般代理目标都需要一个接口,接口方法固定,导致代理目标的新添方法无法代理)
* (介绍:使用javassist自动生成代理目标的接口以待代理使用, 只要代理获取到目标的已有的方法名就可以完成代理的拦截功能)
* 
 * @author WLei May 21, 2011
 */
public class MyProxy {
	// 生成代理类后缀名
	public final static String PROXY_SUFFIX_NAME = "$proxy";

	// 防止代理类重名
	public static int proxyIndex = 1;

	public Object newInstance(Class target, MyInvocationHandler handler) {
		Object proxy = null;
		// 引用处理器接口
		String invocationInter = handler.getClass().getInterfaces()[0]
				.getName();
		// 代理目标类名
		String targetName = target.getName();
		//targetName = targetName.substring(targetName.lastIndexOf(".") + 1);
		System.out.println("targetName:" + targetName);
		// 引用处理器实现名称
		String invocationImpl = handler.getClass().getName();
		try {
			proxy = (Object) generProxy(invocationInter, targetName,
					invocationImpl);
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (CannotCompileException e) {
			e.printStackTrace();
		}
		return proxy;
	}

	@SuppressWarnings("rawtypes")
	public static Object generProxy(String invocationInter, String targetName,
			String invocationImpl) throws InstantiationException,
			IllegalAccessException, CannotCompileException {
		ClassPool cp = ClassPool.getDefault();
		CtClass target = null;
		CtClass proxy = null;
		String proxyName = targetName + PROXY_SUFFIX_NAME + proxyIndex++;
		System.out.println("代理名称:" + proxyName);
		try {
			// 根据目标类生成接口
			target = cp.get(targetName);
			CtMethod[] ctms = target.getDeclaredMethods();
			String targetInterface = "I" + targetName;
			CtClass targertInter = cp.makeInterface(targetInterface);
			String targetIntermtBody = generInterMethodBody(ctms[0]);
			System.out.println("targetInterBody:" + targetIntermtBody);
			CtMethod ctnewMt = CtNewMethod
					.make(targetIntermtBody, targertInter);
			targertInter.addMethod(ctnewMt);// 为生成的目标接口添加方法
			target.addInterface(targertInter);// 为目标添加了一个接口
			// 生成代理类
			proxy = cp.makeClass(proxyName);
			proxy.addInterface(targertInter);// 为代理添加这个接口
			Class ti = targertInter.toClass();
			Method[] tims = ti.getDeclaredMethods();
			for (int i = 0; i < tims.length; i++) {
				System.out.println("tims:" + tims[i].getName());
			}

			// 添加接口的方法到代理
			addMethodToProxy(proxy, tims, invocationInter, invocationImpl,
					targetName);

		} catch (NotFoundException e) {
			e.printStackTrace();
		} catch (CannotCompileException e) {
			e.printStackTrace();
		}
		return (Object) proxy.toClass().newInstance();
	}

	public static void addMethodToProxy(CtClass proxy, Method[] tims,
			String invocationInter, String invocationImpl, String targetName) {
		for (int i = 0; i < tims.length; i++) {
			String methodBody = generMethodBody(tims[i], invocationInter,
					invocationImpl, targetName, i);
			System.out.println("方法体:" + methodBody);
			try {
				CtMethod newMethod = CtNewMethod.make(methodBody, proxy);
				proxy.addMethod(newMethod);
			} catch (CannotCompileException e) {
				e.printStackTrace();
			}
		}
		CtMethod[] ctms = proxy.getDeclaredMethods();
		for (int j = 0; j < ctms.length; j++) {
			System.out.println("代理中的方法:" + ctms[j].getName() + "\n 方法内容:"
					+ ctms[j].getMethodInfo());
		}
	}

	/**
	 * 生成接口方法体的方法
	 * 
	 * @param method
	 * @return
	 * @author WLei May 21, 2011
	 */
	public static String generInterMethodBody(CtMethod method) {
		StringBuffer methodCode = new StringBuffer();
		String visit = new String("public");
		methodCode.append(visit);
		try {
			String returnType = method.getReturnType().getName();
			methodCode.append(" " + returnType);
			String methodName = method.getName();
			methodCode.append(" " + methodName + "(");
			CtClass parameterType[] = method.getParameterTypes();
			int j = parameterType.length;
			for (int k = 0; k < j; k++) {
				if (k == j - 1) {
					methodCode
							.append(parameterType[k].getName() + " param" + k);
				} else {
					methodCode.append(parameterType[k].getName() + " param" + k
							+ " ,");
				}
			}
			methodCode.append(");");
		} catch (NotFoundException e) {
			e.printStackTrace();
		}
		return methodCode.toString();
	}

	/**
	 * 生成代理中的方法体
	 * 
	 * @param method
	 * @param invocationInter
	 * @param invocationImpl
	 * @param targetImpl
	 * @param i
	 * @return
	 * @author WLei May 22, 2011
	 */
	@SuppressWarnings("rawtypes")
	public static String generMethodBody(Method method, String invocationInter,
			String invocationImpl, String targetImpl, int i) {
		StringBuffer methodCode = new StringBuffer();
		// 访问修饰符
		String visit = new String("public");
		methodCode.append(visit);
		// 返回类型
		String returnType = method.getReturnType().getName();
		methodCode.append(" " + returnType);
		// 方法名
		String methodName = method.getName();
		methodCode.append(" " + methodName + "(");
		// 该方法的参数类型和
		Class parameterType[] = method.getParameterTypes();
		int j = parameterType.length;
		for (int k = 0; k < j; k++) {
			if (k == j - 1) {
				methodCode.append(parameterType[i].getName() + " a" + k);
			} else {
				methodCode.append(parameterType[i].getName() + " a" + k + " ,");
			}
		}
		methodCode.append(")");
		// 得到方法的异常
		Class exceptionType[] = method.getExceptionTypes();
		if (exceptionType.length > 0) {
			methodCode.append("throws");
			for (int k = 0; k < exceptionType.length; k++) {
				if (k == exceptionType.length - 1) {
					methodCode.append(" " + exceptionType[i]);
				} else {
					methodCode.append(" " + exceptionType[i] + ",");
				}
			}
		}
		// 构建方法体
		methodCode.append("{\n");
		System.out.println("执行到这里invocationInter名为:" + invocationInter);
		methodCode.append(invocationInter + " handler=new " + invocationImpl
				+ "();\n");
		methodCode.append("Object returnObje=handler.invoke(Class.forName(\""
				+ targetImpl + "\"" + ").newInstance(),Class.forName(\""
				+ targetImpl + "\").getMethods()[" + i + "],");
		// 构建参数的Object[]
		if (parameterType.length > 0) {
			methodCode.append("new Object[]{");
			for (int k = 0; k < parameterType.length; k++) {
				if (i == parameterType.length - 1) {
					methodCode.append("a" + k);
				} else {
					methodCode.append("a" + k + ",");
				}
			}
			methodCode.append("});\n");
		} else {
			methodCode.append("new Object[]{null});\n");
		}

		// 处理返回值
		if (method.getReturnType().isPrimitive()) {
			if (method.getReturnType().equals(Boolean.TYPE))
				methodCode
						.append("return ((Boolean)returnObj).booleanValue();\n");
			else if (method.getReturnType().equals(Integer.TYPE))
				methodCode.append("return ((Integer)returnObj).intValue();\n");

			else if (method.getReturnType().equals(Long.TYPE))
				methodCode.append("return ((Long)returnObj).longValue();\n");

			else if (method.getReturnType().equals(Float.TYPE))
				methodCode.append("return ((Float)returnObj).floatValue();\n");

			else if (method.getReturnType().equals(Double.TYPE))
				methodCode
						.append("return ((Double)returnObj).doubleValue();\n");

			else if (method.getReturnType().equals(Character.TYPE))
				methodCode
						.append("return ((Character)returnObj).charValue();\n");

			else if (method.getReturnType().equals(Byte.TYPE))
				methodCode.append("return ((Byte)returnObj).byteValue();\n");

			else if (method.getReturnType().equals(Short.TYPE))
				methodCode.append("return ((Short)returnObj).shortValue();\n");

		} else {

			methodCode.append("return (" + returnType + ")returnObje;\n");

		}
		methodCode.append("}");
		return methodCode.toString();

	}

}



具体请下载源代码参详----原创
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics