设计模式---动态代理

一.理解:

代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 
按照代理的创建时期,代理类可以分为两种。 
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。 
动态代理:在程序运行时,运用反射机制动态创建而成。 

二.模拟jdk的动态代理

代码

//调用类

package com.d12321.proxy;
import java.lang.reflect.Method;
public class TankLogProxy implements com.d12321.proxy.movable {
com.d12321.proxy.InvocationHander tank;
public TankLogProxy(InvocationHander tank) {
this.tank = tank;
}
@Override
public void run() throws Exception {
Method md = com.d12321.proxy.movable.class.getMethod("run");
tank.invoke(this, md);
}
}
//运行结果
tank start ....
Tank move ....
tank end ....

//动态代理类Proxy(生成代理实例)

package com.d12321.proxy;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
public class Proxy {
public static Object newProxyInstance(Class inter, InvocationHander h) throws Exception{
String rt =  "\n";
String moths= "";
Method[] ms = inter.getMethods();
/*
for(Method m : ms) {
moths += "@Override" +rt+
"public void " + m.getName() +"() {"+rt+
"      System.out.println(\"tank start ....\");" + rt +
"      "+"tank."+m.getName() +"();"+ rt +
"      System.out.println(\"tank end ....\");" + rt +
"}";
}
*/
for(Method m : ms) {
moths += "@Override" +rt+
"public void " + m.getName() +"() throws Exception {"+rt+
"  Method md = "+inter.getName()+".class.getMethod(\"" + m.getName() + "\");"+ rt+
"tank.invoke(this, md);" + rt +
"}";
}
String str =
"package com.d12321.proxy;" + rt + rt +
"import java.lang.reflect.Method;"+rt+
"public class TankLogProxy implements "+inter.getName()+" {"  + rt +
"  com.d12321.proxy.InvocationHander tank;" + rt +
"   public TankLogProxy(InvocationHander tank) {" + rt +
"      this.tank = tank;" + rt +
"   }" + rt +
moths + rt +
" }";
//源码
String filename = System.getProperty("user.dir")+"/src/com/d12321/proxy/TankLogProxy.java";
File f = new File(filename);
FileWriter fw = new FileWriter(f);
fw.write(str);
fw.flush();
fw.close();
//编译
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
Iterable units = fileMgr.getJavaFileObjects(filename);
CompilationTask t = compiler.getTask(null,fileMgr, null, null, null, units);
t.call();
fileMgr.close();
//loader到内存
URL[] urls = new URL[] {new URL("file:/"+System.getProperty("user.dir")+"/src/")};
URLClassLoader ul = new URLClassLoader(urls);
Class c = ul.loadClass("com.d12321.proxy.TankLogProxy");
//生产对象
Constructor ctr = c.getConstructor(InvocationHander.class);
Object m = ctr.newInstance(h);
return m;
}
}

//InvocationHandler接口,调用反射执行对象的方法,在方法上加上需要加上的逻辑

//接口

package com.d12321.proxy;
import java.lang.reflect.Method;
public interface InvocationHander {
public void invoke(Object o, Method m);
}

//实现接口的类

package com.d12321.proxy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TimeInvocationHander implements InvocationHander {
private Object t;
public TimeInvocationHander(Object t) {
super();
this.t = t;
}
public Object getT() {
return t;
}
public void setT(Object t) {
this.t = t;
}
@Override
public void invoke(Object o, Method m) {
System.out.println("tank start ....");
try {
m.invoke(t, new Object[]{});
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println("tank end ....");
}
}

//需要添加逻辑的类

//接口

package com.d12321.proxy;
public interface movable {
void run() throws Exception;
//void move();
}

//类

package com.d12321.proxy;
public class Tank implements movable{
@Override
public void run() {
System.out.println("Tank move ....");
}
}

总结:

首先,Tank是实现movable接口的实例,需要添加逻辑的类,TimeInvocationHandler是实现InvocationHandler接口的实例,里面的采用Method m.invoke(Object o, , )方法调m方法,实现了向方法上添加逻辑,Proxy能够生成任意对象和添加逻辑类的实例类,就像jdk中的动态代理一样

位于java.lang.reflect.Proxy

用到的知识点

1.java的反射机制,方法如何执行

2.java如何拿到编译器,编译对象

3.java如何loader对象到内存

4.java如何生成实例对象

5.拿到当前项目的路径system.getProperty("userr.dir")

你可能感兴趣的:(动态代理)