`
qihuiyong6
  • 浏览: 39479 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

javassi实现t动态代理模式

 
阅读更多
最近研究了一下javassist框架,目前我对它的理解是它是一个动态创建类的框架。作为自己的学习的阶段成果使用它模拟了一个jdk动态代理的实现,在这里和大家分享一下。其实这反射的编程比想象中的麻烦一点的,期间遇到很多不好解决的问题放到javassist就不能执行,还好自己还是坚持完成了。如果我的实现方式有可优化或者漏洞欢迎大家指出。

主要实现类
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: 创建代理对象. <br/>
	 * @param interfaceClass 接口定义
	 * @param implClass 实现类
	 * @param invocationClass 代理类
	 * @return
	 * @throws Exception 
	 */
	public static <T> T newProxyInstance(Class<T> 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:生成返回代码 . <br/>
	 * @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: 获取方法的代码指定实现方法的代码. <br/>
	 * @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: . <br/>
	 * 
	 * @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);
	}
}

输出结果:



  • 大小: 56.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics