最近研究了一下javassist框架,目前我对它的理解是它是一个动态创建类的框架。作为自己的学习的阶段成果使用它模拟了一个jdk动态代理的实现,在这里和大家分享一下。其实这反射的编程比想象中的麻烦一点的,期间遇到很多不好解决的问题放到javassist就不能执行,还好自己还是坚持完成了。如果我的实现方式有可优化或者漏洞欢迎大家指出。
[size=medium][b]主要实现类[/b][/size]
MyProxy:提供一个静态方法创建代理对象,主要代码都在这里。整理思路是使用它动态的创建一个类然后使用MyInvocationHandler的实现调用业务接口实现类的具体方法,这样就完成了动态代理一个类的基本操作;
MyInvocationHandler:提供一个动态代理的接口供使用者使用,比较简单;
[size=medium][b]MyProxy[/b][/size]
[size=medium][b]MyInvocationHandler[/b][/size]
[size=medium][b]测试代码:[/b][/size]
[size=medium][b]业务接口类IEcho[/b][/size]
[size=medium][b]业务接口实现类EchoEn [/b][/size]
[size=medium][b]代理模式接口实现类:TestInvocationHandler[/b][/size]
[size=medium][b]测试代码[/b][/size]
[size=medium][b]输出结果:[/b][/size]
[img]http://dl2.iteye.com/upload/attachment/0119/9171/0cfd4dfa-01a5-3bd4-886f-5addb38220b2.png[/img]
[size=medium][b]主要实现类[/b][/size]
MyProxy:提供一个静态方法创建代理对象,主要代码都在这里。整理思路是使用它动态的创建一个类然后使用MyInvocationHandler的实现调用业务接口实现类的具体方法,这样就完成了动态代理一个类的基本操作;
MyInvocationHandler:提供一个动态代理的接口供使用者使用,比较简单;
[size=medium][b]MyProxy[/b][/size]
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;
}
}
[size=medium][b]MyInvocationHandler[/b][/size]
package qhy.demo.javassist.myDynamicProxy;
import java.lang.reflect.Method;
public interface MyInvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
[size=medium][b]测试代码:[/b][/size]
[size=medium][b]业务接口类IEcho[/b][/size]
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();
}
[size=medium][b]业务接口实现类EchoEn [/b][/size]
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;
}
}
[size=medium][b]代理模式接口实现类:TestInvocationHandler[/b][/size]
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;
}
}
[size=medium][b]测试代码[/b][/size]
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);
}
}
[size=medium][b]输出结果:[/b][/size]
[img]http://dl2.iteye.com/upload/attachment/0119/9171/0cfd4dfa-01a5-3bd4-886f-5addb38220b2.png[/img]