主要实现类
MyProxy:提供一个静态方法创建代理对象,主要代码都在这里。整理思路是使用它动态的创建一个类然后使用MyInvocationHandler的实现调用业务接口实现类的具体方法,这样就完成了动态代理一个类的基本操作;
MyInvocationHandler:提供一个动态代理的接口供使用者使用,比较简单;
MyProxy
package qhy.demo.javassist.myDynamicProxy; import java.lang.reflect.Modifier; import javassist.ClassPool; import javassist.CtClass; import javassist.CtField; import javassist.CtField.Initializer; import javassist.CtMethod; public class MyProxy { private static int proxyIndex = 1; private static String PROXY_SUFFIX="_$Proxy_"; //代理类的名称 /** * * Description: 创建代理对象.
* @param interfaceClass 接口定义 * @param implClass 实现类 * @param invocationClass 代理类 * @return * @throws Exception */ public staticT newProxyInstance(Class interfaceClass, Class extends T> implClass, Class extends MyInvocationHandler> invocationClass) throws Exception { String interfaceName = interfaceClass.getName(); //业务接口 String implClassName = implClass.getName();//业务实现类,被代理的对象 String invocationImplClassName = invocationClass.getName(); //代理模式接口实现类 //开始生成代理类实例 String proxyClassName = interfaceName + PROXY_SUFFIX + proxyIndex++; ClassPool cp = ClassPool.getDefault(); CtClass proxyImplClass = cp.makeClass(proxyClassName); //1、设置实现类的 接口 CtClass interfaceCtClass = cp.getCtClass(interfaceName); proxyImplClass.addInterface(interfaceCtClass); CtMethod[] interfaceCtMethods = interfaceCtClass.getDeclaredMethods(); if(interfaceCtMethods !=null && interfaceCtMethods.length > 0){ //2、注入invocationHandler 属性 CtField newField = new CtField(cp.get(invocationImplClassName), "testInvoke", proxyImplClass); newField.setModifiers(Modifier.PRIVATE); proxyImplClass.addField(newField, Initializer.byExpr(" testInvoke = new "+invocationImplClassName+"();")); int i = 0; for (CtMethod ctMethod : interfaceCtMethods) { //3、循环创建接口的实现方法 //3.1、创建方法定义 String methodName = ctMethod.getName(); CtClass returnType = ctMethod.getReturnType(); CtClass[] paramTypes = ctMethod.getParameterTypes(); CtMethod newMethod = new CtMethod(returnType, methodName, paramTypes, proxyImplClass); newMethod.setModifiers(Modifier.PUBLIC); //3.1、创建方法体 StringBuffer body = new StringBuffer(); body.append("{"); //3.2、生成获取指定实现类方法的代码 String getMethodArg = generateImplGetMethodCode(methodName,implClassName,paramTypes); body.append("\n Object result = testInvoke.invoke(Class.forName(\""+implClassName+"\").newInstance(),"+getMethodArg+",$args);"); //3.3、生成获取指定实现类方法的代码 String returnCode = generateImplReturnCode(returnType,"result"); if(returnCode !=null && returnCode.trim().length()>5){ body.append(returnCode); } // body.append("\n return ("+returnType.getName()+")result;"); body.append("}"); newMethod.setBody(body.toString()); proxyImplClass.addMethod(newMethod); i++; } } Object obj = proxyImplClass.toClass().newInstance(); return (T)obj; } /** * Description:生成返回代码 .
* @param returnType * @param string * @return */ private static String generateImplReturnCode(CtClass returnType, String returnVariableName) { String returnCode = null; if(returnType != CtClass.voidType){ if(returnType.isPrimitive()){ if(returnType == CtClass.intType){ returnCode = "\n return (("+Integer.class.getName()+")"+returnVariableName+").intValue();"; }else if(returnType == CtClass.byteType){ returnCode = "\n return (("+Byte.class.getName()+")"+returnVariableName+").byteValue();"; }else if(returnType == CtClass.booleanType){ returnCode = "\n return (("+Boolean.class.getName()+")"+returnVariableName+").booleanValue();"; }else if(returnType == CtClass.charType){ returnCode = "\n return (("+Character.class.getName()+")"+returnVariableName+").charValue();"; }else if(returnType == CtClass.doubleType){ returnCode = "\n return (("+Double.class.getName()+")"+returnVariableName+").doubleValue();"; }else if(returnType == CtClass.floatType){ returnCode = "\n return (("+Float.class.getName()+")"+returnVariableName+").floatValue();"; }else if(returnType == CtClass.longType){ returnCode = "\n return (("+Long.class.getName()+")"+returnVariableName+").longValue();"; }else if(returnType == CtClass.shortType){ returnCode = "\n return (("+Short.class.getName()+")"+returnVariableName+").shortValue();"; } }else{ returnCode = "\n return ("+returnType.getName()+") "+returnVariableName+";"; } } return returnCode; } /** * Description: 获取方法的代码指定实现方法的代码.
* @param methodName * @param implClassName * @param paramTypes */ private static String generateImplGetMethodCode(String methodName, String implClassName, CtClass[] paramTypes) { //没用约束的方法这么定义获取方式 String getMethodArg="Class.forName(\""+implClassName+"\").getDeclaredMethod(\""+methodName+"\", null)"; if(paramTypes!=null && paramTypes.length>0){ StringBuffer sb = new StringBuffer("new Class[]{"); int paramLength = paramTypes.length; for (int j = 0; j < paramLength; j++) { String calssName = paramTypes[j].getName(); if(j == (paramLength-1)){ sb.append(calssName).append(".class"); }else{ sb.append(calssName).append(".class").append(","); } } sb.append("}"); getMethodArg = "Class.forName(\""+implClassName+"\").getDeclaredMethod(\""+methodName+"\","+sb.toString()+")"; } return getMethodArg; } }
MyInvocationHandler
package qhy.demo.javassist.myDynamicProxy; import java.lang.reflect.Method; public interface MyInvocationHandler { public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; }
测试代码:
业务接口类IEcho
package qhy.demo.javassist.myDynamicProxy.test; import java.util.Date; public interface IEcho { public void echo(); public int echo(int aa); public Boolean echo1(int aa,String user); public long getCurrentType(); public Date getDate(String aa); public ObjectModel echo(ObjectModel model); public char getChar(); }
业务接口实现类EchoEn
package qhy.demo.javassist.myDynamicProxy.test; import java.util.Date; public class EchoEn implements IEcho { @Override public void echo() { System.out.println("hello "+233434+"!"); } @Override public long getCurrentType() { System.out.println("getCurrentType"); return System.currentTimeMillis(); } @Override public Boolean echo1(int aa, String user) { System.out.println("getDate;param="+aa+","+user); // TODO Auto-generated method stub return true; } @Override public char getChar() { return 'A'; } @Override public Date getDate(String aa) { System.out.println("getDate;param="+aa); // TODO Auto-generated method stub return null; } @Override public ObjectModel echo(ObjectModel model) { System.out.println("echo(ObjectModel model)>>>>>>>param="+model.getName()); ObjectModel result = new ObjectModel("郑文玉", 33, 10023L); return result; } @Override public int echo(int aa) { System.out.println("我是AAA"+aa+"!"); return -98; } }
代理模式接口实现类:TestInvocationHandler
package qhy.demo.javassist.myDynamicProxy.test; import java.lang.reflect.Method; import qhy.demo.javassist.myDynamicProxy.MyInvocationHandler; public class TestInvocationHandler implements MyInvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("执行前:拦截111111111111111"); Object result = method.invoke(proxy, args); System.out.println("执行后:拦截22222222222222222"); return result; } }
测试代码
package qhy.demo.javassist.myDynamicProxy.test; import qhy.demo.javassist.myDynamicProxy.MyProxy; public class Test { /** * Description: .
* * @param args * @throws Exception */ public static void main(String[] args) throws Exception { IEcho echo = MyProxy.newProxyInstance(IEcho.class, EchoEn.class, TestInvocationHandler.class); echo.echo(); int aa = echo.echo(888); System.err.println(">>>>>>>>>>>>>>"+aa); Boolean bool = echo.echo1(555, "qihyyy"); System.err.println(">>>>>>>>>>>>>>"+bool); ObjectModel result = new ObjectModel("qiqi玉", 31, 6013L); ObjectModel objModel = echo.echo(result); System.err.println(">>>>objModel>>>>>>>>>>"+objModel.getName()+"--"+objModel.getAge()+"--"+objModel.getCurrentTime()); char cha = echo.getChar(); System.err.println(">>>>getChar>>>>>>>>>>"+cha); } }
输出结果: