一:具体类
Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:
InvocationHandler
Proxy
二:具体运用
在不变原基础方法的情况下,对其开头 结尾,加事务,日志,拦截器,等。。。。
动态代理具体的运用,如spring中的关键技术AOP,
三:代码模拟Proxy 和 InvocationHandler
需求:在不变原方法的情况下,在方法前后分别加上日志
第一阶段
新建接口类,
package com.wem.Dome;
/**
* Created by Administrator on 2016-08-13.
*/
public interface Vehicle {
public void run();
}
新建实现类
package com.wem.Dome;
/**
* Created by Administrator on 2016-08-13.
*/
public class Car implements Vehicle {
@Override
public void run() {
System.out.println("轰隆隆的启动了");
}
}
在不变原方法的情况下,也就是说不能再修改Car中的run方法了,可以想到的方法是,如下方法
package com.wem.Dome;
/**
* Created by Administrator on 2016-08-15.
*/
public class AddLog {
public void addlog(Vehicle vehicle){
System.out.println("start log");
Vehicle v = vehicle;
v.run();
System.out.println("stop log");
}
}
但是,如果我想再添加一个事务呢?或者,在不变原方法的情况下拦截某些数据,那么得继续增加类,或者增加方法来做这样的操作,
那么根据这个问题,想能不能建立一个代理类,来做这些事情。
MyProxy
package com.wem.Dome;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
/**
* Created by Administrator on 2016-08-13.
*/
public class MyProxy {
public static Object newProxyInstance(Class interf,MyInvocationHandler h) {
String rn = "\r\n";
//获取接口中有多少方法
Method[] methods =interf.getMethods();
String MethodStr = "";
//组合方法
for(Method m :methods){
MethodStr = " @Override " +rn+
" public "+m.getReturnType().getName()+" "+m.getName()+"(){" + rn +
" try{"+ rn +
" Method md ="+interf.getName()+".class.getMethod(\""+m.getName()+"\");"+ rn +
" h.invoke(this,md);"+ rn +
" }catch(Exception e){" +rn+
" e.printStackTrace();"+rn+
" }"+rn+
" }"+rn;
}
String str ="import java.lang.reflect.Method;"+ rn +
"import com.wem.Dome.MyInvocationHandler;"+ rn +
"public class $Proxy implements "+interf.getName()+"{ " + rn +
" MyInvocationHandler h;"+ rn +
" public $Proxy(MyInvocationHandler h){" + rn +
" this.h =h;" + rn+
" }"+ rn+
MethodStr+
"}";
String fileName = "D:/src/$Proxy.java";
File file = new File(fileName);
try {
//生成.java文件,
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(str.getBytes());
fileOutputStream.flush();
fileOutputStream.close();
//生成.class文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null,null,null);
Iterable units = fileManager.getJavaFileObjects(fileName);
JavaCompiler.CompilationTask t = compiler.getTask(null,fileManager,null,null,null,units);
t.call();
fileManager.close();
//获取class文件的路径
URL[] urls = new URL[]{new URL("file:/"+"D:/src/")};
//class加载器
URLClassLoader url = new URLClassLoader(urls);
//把class文件加入内存中
Class c = url.loadClass("$Proxy");
System.out.println(c);
//获取类的有参数的构造函数
Constructor ctr = c.getConstructor(MyInvocationHandler.class);
//根据构造函数获取生成对象,传入对象h
Object p = ctr.newInstance(h);
return p;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
建立MyInvocationHandler
package com.wem.Dome;
import java.lang.reflect.Method;
/**
* Created by Administrator on 2016-08-13.
*/
public interface MyInvocationHandler {
public Object invoke(Object o, Method method);
}
创建
MyInvocationHandler实现类
package com.wem.Dome;
import java.lang.reflect.Method;
/**
* Created by Administrator on 2016-08-13.
*/
public class LogMyInvocationHandler implements MyInvocationHandler {
private Object object;
public LogMyInvocationHandler(Object o){
this.object = o;
}
@Override
public Object invoke(Object o, Method method) {
Object restul= null;
try {
//开启日志
System.out.println("Start log");
//以本例为例,method = public abstract void com.wem.Dome.Vehicle.run()
restul = method.invoke(object);
//日志结束
System.out.println("Stop log");
} catch (Exception e) {
e.printStackTrace();
}
return restul;
}
}
效果显示
main方法
public static void main(String[] arge){
Car car = new Car();
MyInvocationHandler lm = new LogMyInvocationHandler(car);
Vehicle v =(Vehicle) MyProxy.newProxyInstance(Vehicle.class,lm);
v.run();
}