* 接口随着代理目标自动生成 (背景:一般代理目标都需要一个接口,接口方法固定,导致代理目标的新添方法无法代理)
* (介绍:使用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(); } }
具体请下载源代码参详----原创