代理模式的作用:AOP、拦截器、解耦 ...
1. 静态代理:
2. 动态代理:
3. 自己手写动态代理:
-
结构
- 代理类Proxy
package xin.zero2one.proxy.myproxy;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* Created by jundo on 2018/5/30.
*/
public class MyProxy {
private final static String ln = "\r\n";
public static Object newProxyInstance(MyClassLoader loader, Class>[] interfaces, MyInvocationHandler h){
try {
//生成$Proxy.java文件,只针对Car对象
String src = generateSrc(interfaces);
//将$Proxy.java保存到classpath
String classpath = MyProxy.class.getResource("").getPath();
File proxyFile = new File(classpath + "$Proxy0.java");
FileWriter fw = new FileWriter(proxyFile);
fw.write(src);
fw.flush();
fw.close();
//编译$Proxy.java
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
Iterable extends JavaFileObject> iterable = manager.getJavaFileObjects(proxyFile);
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
task.call();
manager.close();
//将$Proxy.java加载到内存中
System.out.println("find class");
Class> proxy0 = loader.findClass("$Proxy0");
System.out.println("find ok");
Constructor> constructor = proxy0.getConstructor(MyInvocationHandler.class);
return constructor.newInstance(h);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
private static String generateSrc(Class>[] interfaces){
StringBuffer sb = new StringBuffer();
sb.append("package xin.zero2one.proxy.myproxy;" + ln);
sb.append("import xin.zero2one.bean.Car;" + ln);
sb.append("import xin.zero2one.proxy.myproxy.MyInvocationHandler;" + ln);
sb.append("import java.lang.reflect.Method;" + ln);
sb.append("public class $Proxy0 implements " + interfaces[0].getName() + "{" + ln);
sb.append("MyInvocationHandler h;" + ln);
sb.append("public $Proxy0(MyInvocationHandler h) { " + ln);
sb.append("this.h = h;");
sb.append("}" + ln);
for (Method m : interfaces[0].getMethods()){
sb.append("public " + m.getReturnType().getName() + " " + m.getName() + "() {" + ln);
sb.append("try{" + ln);
sb.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + m.getName() + "\",new Class[]{});" + ln);
sb.append("this.h.invoke(this,m,null);" + ln);
sb.append("}catch(Throwable e){" + ln);
sb.append("e.printStackTrace();" + ln);
sb.append("}");
sb.append("}");
}
sb.append("}" + ln);
return sb.toString();
}
}
- MyInvocationHandler
package xin.zero2one.proxy.myproxy;
import java.lang.reflect.Method;
/**
* Created by jundo on 2018/5/30.
*/
public interface MyInvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
- MyClassLoader
package xin.zero2one.proxy.myproxy;
import java.io.*;
/**
* Created by jundo on 2018/5/30.
*/
public class MyClassLoader extends ClassLoader{
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
String classpath = MyClassLoader.class.getResource("").getPath();
String className = MyClassLoader.class.getPackage().getName() + "." + name;
String filePath = name.replaceAll("\\.", "/");
File classFile = new File(classpath, filePath + ".class");
if (classFile.exists()) {
FileInputStream fis = null;
ByteArrayOutputStream out = null;
try {
fis = new FileInputStream(classFile);
out = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
return defineClass(className, out.toByteArray(), 0, out.size());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return null;
}
}
- 被代理接口Car
package xin.zero2one.bean;
/**
* Created by jundo on 2018/5/29.
*/
public interface Car {
void getCar();
}
- Car实现类
package xin.zero2one.bean;
/**
* Created by jundo on 2018/5/29.
*/
public class Tesla implements Car{
@Override
public void getCar() {
System.out.println("get tesla");
}
}
- Car代理类
package xin.zero2one.proxy;
import xin.zero2one.bean.Car;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by jundo on 2018/5/29.
*/
public class CarProxy implements InvocationHandler{
private Car car;
public Object getInstance(Car car){
this.car = car;
Class> clazz = car.getClass();
Class>[] interfaces = clazz.getInterfaces();
Car obj = (Car) Proxy.newProxyInstance(clazz.getClassLoader(), interfaces, this);
return obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("找车子啦");
System.out.println(method == null);
method.invoke(this.car,args);
System.out.println("就决定是你了");
return null;
}
}
- 测试类
package xin.zero2one.proxy.myproxy;
import xin.zero2one.bean.Car;
import xin.zero2one.bean.Tesla;
/**
* Created by jundo on 2018/5/30.
*/
public class MyProxyTest {
public static void main(String[] args) {
MyCarProxy proxy = new MyCarProxy();
Car car = (Car)proxy.getInstance(new Tesla());
car.getCar();
}
}