一.我对动态代理的理解
1.动态生成代理类java源文件
2.将代理类java源文件
编译为代理类class字节码
文件
3.将代理类class字节码文件 自动加载到内存中
4.将自动加载到内存的代理类class字节码进行实例化为 代理对象
5.有了代理对象,就可以使用代理对象中的方法调用被代理对象的方法了;
二.动态代理的实现流程
1.编写接口MoveAble 有move方法
package proxy.statics;
/**
* 移动接口
* @author lxf
*
*/
public interface MoveAble {
public void move();
}
2.编写被代理类Car实现MoveAble接口,并实现move方法写业务罗辑;
package proxy.statics;
import java.util.Random;
/**
* 被代理类,汽车
* @author lxf
* @2017-07-06
*/
public class Car implements MoveAble {
@Override
public void move() {
//System.out.println("被代理对象---我是汽车对象本身:"+this.getClass().getName());
//实现开车
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶中...");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.编写InvocationHandler接口(包含myinvoke方法)
注意:这里的InvocationHandler并不是java.lang.refect包下面的InvocationHandler
package proxy.dynamic.custom;
import java.lang.reflect.Method;
/**
* 事务处理接口
* @author lxf
*
*/
public interface InvocationHandler {
/**
* 参数:Object obj 属于代理对象
* 参数:Method method 属于代理对象的方法
*/
public void myinvoke(Object obj, Method method);
}
4.编写TimerHandler类实现自己InvocationHandler接口中的myinvoke方法(用来调用被代理对象的方法,还有其他额外的业务逻辑)
package proxy.dynamic.custom;
import java.lang.reflect.Method;
/**
* 实现自己定义的事务处理接口proxy.dynamic.custom.InvocationHandler
* @author lxf
*
*/
public class TimerHandler implements InvocationHandler {
//代理对象
private Object target;
public TimerHandler(Object target) {
super();
this.target = target;
}
/**
* 参数:Object obj 属于代理对象
* 参数:Method method 属于代理对象的方法
*/
@Override
public void myinvoke(Object obj, Method method) {
// TODO Auto-generated method stub
try {
//开始时间 " + br +
Long start = System.currentTimeMillis();
System.out.println("汽车开始行驶...");
method.invoke(target);
//结束时间 " + br +
Long end = System.currentTimeMillis();
System.out.println("汽车结束行驶...行驶话费了:" + (end-start) + "ms");
//视频听到3-3 3:42秒
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.编写生成代理类
的类Proxy,它的主要功能是 一步骤
中的所有流程;
package proxy.dynamic.custom;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import org.apache.commons.io.FileUtils;
import javax.tools.JavaCompiler.CompilationTask;
import proxy.statics.Car;
import proxy.statics.MoveAble;
/**
* 动态代理类
* @author lxf
* 参数:
* Class 代理类和被代理类实现的接口
* InvocationHandler h 自己实现的事务处理器proxy.dynamic.custom.TimerHandler
*
*/
public class Proxy {
/**
* 自己实现JDK生成动态代理类及对象
* @param infce 接口class,有了接口就可以通过接口获取接口中定义的方法,为生成代理类而用
* @param h 自己创建的proxy.dynamic.custom.InvocationHandler 事务处理器(处理主要业务罗辑)
* 事务处理器中包含被代理对象Car,具体处理业务罗辑的代码
* @return
* @throws IOException
*/
public static Object newProxyInstance(Class infce, InvocationHandler h) throws IOException
{
String br = "\n"; //换行符
String methodStr = "";
//获取接口中所有的方法,遍历组合为代理类的方法
for(Method m : infce.getMethods()){
methodStr += " @Override" + br +
" public void " + m.getName() + "() {" + br +
" try{" + br +
" Method md = " + infce.getName() + ".class.getMethod(\""
+ m.getName() + "\");" + br +
" h.myinvoke(this,md);" +br+
" }catch(Exception e){ e.printStackTrace();}" + br +
" }" ;
}
/**
* 动态代理类字符串
*/
String str =
" package proxy.dynamic.custom; " + br +
" import proxy.dynamic.custom.InvocationHandler; " + br +
" import java.lang.reflect.Method;" + br +
" public class $Proxy0 implements "+infce.getName()+"{ " + br +
" private InvocationHandler h; " + br +
" public $Proxy0( InvocationHandler h ) " + br +
" { " + br +
" this.h = h; " + br +
" } " + br +
methodStr + br +
"}";
/*
* 自行实现动态代理的流程
* 1. 动态生成代理类.java源文件
*/
//获取当前项目路径,/home/lxf/workspaceEE/proxy
String filename = System.getProperty("user.dir") + "/bin/proxy/dynamic/custom/$Proxy0.java";
System.out.println(filename);
File file = new File(filename);
FileUtils.writeStringToFile(file, str);
/*
* 2. 将动态生成的代理类.java源文件编译为class字节码文件
*/
//编译
//拿到编译器
JavaCompiler complier = ToolProvider.getSystemJavaCompiler();
//文件管理者
StandardJavaFileManager fileMgr =
complier.getStandardFileManager(null, null, null);
//获取文件
Iterable units = fileMgr.getJavaFileObjects(filename);
//编译任务
CompilationTask t = complier.getTask(null, fileMgr, null, null, null, units);
//进行编译
t.call();
fileMgr.close();
/**
* load到内存中
*/
ClassLoader cl = ClassLoader.getSystemClassLoader();
Class c;
try {
c = cl.loadClass("proxy.dynamic.custom.$Proxy0");
//System.out.println(c.getName());
//通过构造器返回代理对象
Constructor ctr = c.getConstructor(InvocationHandler.class);
return ctr.newInstance(h);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
4.测试
package proxy.dynamic.custom;
import java.io.IOException;
import proxy.statics.Car;
import proxy.statics.MoveAble;
/**
* 测试自己实现JDK动态代理实现思路
* @author lxf
* @date 2017-07-07
*/
public class testMain {
public static void main(String[] args) throws IOException
{
//实例化被代理类
Car car = new Car();
//实例化事务处理器
InvocationHandler h = new TimerHandler(car);
//生成代理对象
MoveAble m = (MoveAble)Proxy.newProxyInstance(MoveAble.class,h);
//调用代理对象的方法
m.move();
}
}
执行结果:
/home/lxf/workspaceEE/proxy/bin/proxy/dynamic/custom/$Proxy0.java
汽车开始行驶...
汽车行驶中...
汽车结束行驶...行驶话费了:975ms
动态生成代理类/home/lxf/workspaceEE/proxy/bin/proxy/dynamic/custom/$Proxy0.java的代码如下:
package proxy.dynamic.custom;
import proxy.dynamic.custom.InvocationHandler;
import java.lang.reflect.Method;
public class $Proxy0 implements proxy.statics.MoveAble{
private InvocationHandler h;
public $Proxy0( InvocationHandler h )
{
this.h = h;
}
@Override
public void move() {
try{
Method md = proxy.statics.MoveAble.class.getMethod("move");
h.myinvoke(this,md);
}catch(Exception e){ e.printStackTrace();}
}
}