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();

}

}



具体请下载源代码参详----原创
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值