1.0 被代理类接口
package com.sheting.reflect.proxy.demo1;
/**
* created by zheTing on 2018-03-06 14:07
*/
public interface HelloWorld {
void sayHello(String name);
}
2.0 被代理类,接口的实现
package com.sheting.reflect.proxy.demo1;
/**
* created by zheTing on 2018-03-06 14:08
*/
public class HelloWorldImpl implements HelloWorld{
@Override
public void sayHello(String name) {
System.out.println("我是被代理类。 Hello " + name);
}
}
第3.0、4.0是把动态代理要处理的业务抽象出一个接口和接口的实现。
3.0 增强被代理类方法的接口
package com.sheting.reflect.proxy.demo1;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* created by zheTing on 2018-03-06 14:02
*/
public interface InvocationHandler {
Object invoke(Method method, Object o, Object... params) throws InvocationTargetException, IllegalAccessException;
}
4.0 增强被代理类方法接口的实现
package com.sheting.reflect.proxy.demo1;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Create Time: 2018-03-06 15:34
* @author sheting
*/
public class LogHandler implements InvocationHandler {
@Override
public Object invoke(Method method, Object o, Object... params) throws InvocationTargetException, IllegalAccessException {
System.out.println("start...");
Object invoke = method.invoke(o, params);
System.out.println("eng...");
return invoke;
}
}
5.0 模拟JDK 的动态代理生成类
package com.sheting.reflect.proxy.demo1;
import org.apache.commons.io.FileUtils;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.concurrent.atomic.AtomicLong;
/**
* created by zheTing on 2018-03-06 14:03
*/
public class Proxy {
private static final String RT = "\r\n";
public static final AtomicLong proxyNum = new AtomicLong(0);
/**
* 第一个参数是 被代理接口
* 第二个参数是 被代理接口的实现 的对象
* 第三个参数是 代理对象
*/
public static Object newProxyInstance(Class interfaceObj, Object obj, InvocationHandler handler) throws Exception {
Method[] methods = interfaceObj.getMethods();
StringBuilder b = new StringBuilder();
for (Method method : methods) {
int parameterCount = method.getParameterCount();
Class<?>[] parameterTypes = method.getParameterTypes();
StringBuilder paramStr = new StringBuilder();
StringBuilder paramClasses = new StringBuilder();
for (int i = 0; i < parameterCount; i++) {
paramStr.append(parameterTypes[i].getName()).append(" ").append("arg").append(i).append(",");
paramClasses.append(parameterTypes[i].getName()).append(".class,");
}
//截掉最后一个逗号
String subParamStr = paramStr.substring(0, paramStr.length() - 1);
String subParamClasses = paramClasses.substring(0, paramClasses.length() - 1);
b.append(" @Override" + RT)
.append(" public void " + method.getName() + "(" + subParamStr + ") {" + RT)
.append(" try {" + RT)
.append(" Method method = " + interfaceObj.getName() + ".class.getMethod(\"" + method.getName() + "\", " + subParamClasses + ");" + RT)
.append(" handler.invoke(method, obj, arg0);" + RT)
.append(" } catch (Exception e) {" + RT)
.append(" e.printStackTrace();}" + RT)
.append(" }" + RT)
;
}
long num = proxyNum.getAndIncrement();
//声明一段源码
String sourceCode =
"package com.sheting.reflect.proxy.demo1;" + RT +
"import java.lang.reflect.Method;" + RT +
"/**" + RT +
" * Created by sheting on 2018/3/6." + RT +
"* 聚合模式实现静态代理" + RT +
"*/" + RT +
"public class $Proxy" + num + " implements " + interfaceObj.getName() + " {" + RT +
" private " + interfaceObj.getName() + " obj;" + RT +
" private InvocationHandler handler;" + RT + RT +
" public $Proxy" + num + "(" + interfaceObj.getName() + " obj, InvocationHandler handler){" + RT +
" this.obj = obj;" + RT +
" this.handler = handler;" + RT +
" }" + RT +
b.toString() +
"}";
String filename = System.getProperty("user.dir") + "/src/main/java/com/sheting/reflect/proxy/demo1/$Proxy" + num + ".java";
File file = new File(filename);
//使用org.apache.commons.io.FileUtils.writeStringToFile()将源码写入磁盘
//并不是一定要生成文件,如果可以直接生成二进制代码load到JVM中,则不必要那么麻烦生成文件了
FileUtils.writeStringToFile(file, sourceCode);
//获得当前系统中的编译器
JavaCompiler complier = ToolProvider.getSystemJavaCompiler();
//获得文件管理者
StandardJavaFileManager fileMgr = complier.getStandardFileManager(null, null, null);
Iterable its = fileMgr.getJavaFileObjects(filename);
//编译任务
JavaCompiler.CompilationTask task = complier.getTask(null, fileMgr, null, null, null, its);
//开始编译
task.call();
fileMgr.close();
//类加载
URL[] urls = new URL[]{new URL("file:/" + System.getProperty("user.dir") + "/src")};
URLClassLoader urlClassLoader = new URLClassLoader(urls);
Class cls = urlClassLoader.loadClass("com.sheting.reflect.proxy.demo1.$Proxy" + num);
//生成代理类对象
Constructor ct = cls.getConstructor(interfaceObj, InvocationHandler.class);
return ct.newInstance(obj, handler);
}
}
动态生成的类:
package com.sheting.reflect.proxy.demo1;
import java.lang.reflect.Method;
/**
* Created by sheting on 2018/3/6.
* 聚合模式实现静态代理
*/
public class $Proxy0 implements com.sheting.reflect.proxy.demo1.HelloWorld {
private com.sheting.reflect.proxy.demo1.HelloWorld obj;
private InvocationHandler handler;
public $Proxy0(com.sheting.reflect.proxy.demo1.HelloWorld obj, InvocationHandler handler){
this.obj = obj;
this.handler = handler;
}
@Override
public void sayHello(java.lang.String arg0) {
try {
Method method = com.sheting.reflect.proxy.demo1.HelloWorld.class.getMethod("sayHello", java.lang.String.class);
handler.invoke(method, obj, arg0);
} catch (Exception e) {
e.printStackTrace();}
}
}
6.0 测试类
package com.sheting.reflect.proxy.demo1;
/**
* created by zheTing on 2018-03-06 14:04
*/
public class Test {
public static void main(String[] args) throws Exception {
HelloWorld proxyObj = (HelloWorld) Proxy.newProxyInstance(HelloWorld.class, new HelloWorldImpl(), new LogHandler());
proxyObj.sayHello("sheting");
}
}
运行结果: