代理模式的定义:
为其他对象提供一种代理,以控制对这个对象的访问。代理对象起到了一个中介的作用,可以去掉功能服务、增加额外服务。
JDK动态代理:
1.只能代理实现了接口的类
2.没有实现接口的类不能实现JDK的动态代理
CGLIB动态代理:
1.针对类实现代理的
2.对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用
Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:
1. Interface InvocationHandler:该接口中仅定义了一个方法
public object invoke(Object obj,Method methdo,Object[] args)在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。
2.Proxy:该类为动态代理类
static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在接口中声明过的方法)。
实现思路
实现功能:通过Proxy的newProxyInstance返回代理对象(代理任意对象任意方法)
1.声明一段源码(动态产生代理)
2.编译源码(JDK Compiler API),产生新的类(代理类)
3.将这个类load到内存中,产生一个新的对象(代理对象)
4.return代理对象
实现代码
//被代理类
public class Car implements Moveable {
public void move() {
System.out.println("汽车开始行驶!");
}
}
//实现的接口
public interface Moveable {
void move();
}
//Proxy代理类(主要代码)
//代理类
public class Proxy {
public static Object newProxyInstance(Class infce, InvocationHandler h) throws Exception{
String rt = "\r\n";
String methodStr = "";
for (Method m : infce.getMethods()){
//methodStr为重写的需要代理方法(car.move())
methodStr += " //@Override" + rt +
" public void " + m.getName() + " (){" + rt +
"try{" + rt +
"Method md = " + infce.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt +
"h.invoke(this,md);" + rt +
"}catch (Exception e){" + rt +
"e.printStackTrace();" + rt +
"}" + rt +
" }";
}
//拷贝源代码(CarTimeProxy类中的代码) 更改文件名为$Proxy0(模仿jdk命名) 修改类名 方法名 参数为传入获取
String str =
"package com.demo.proxy;" + rt +
"import java.lang.reflect.Method;" + rt +
"import com.demo.proxy.InvocationHandler;" + rt +
"public class $Proxy0 implements " + infce.getName() + "{" + rt +
"private InvocationHandler h;" + rt +
"public $Proxy0(InvocationHandler h) {" + rt +
" super();" + rt +
" this.h = h;" + rt +
" }" + rt +
//methodStr为重写的需要代理方法
methodStr + rt +
"};";
//准备编译.java文件
//文件路径 取当前应用(项目)所在路径 放到bin目录下方便编译
String filename = System.getProperty("user.dir") + File.separator + "bin" + File.separator + "com" +
File.separator + "demo" + File.separator + "proxy" + File.separator + "$Proxy0.java";
//生成文件
File file = new File(filename);
//源码生成到java文件中(需要导commons-io的jar包)
FileUtils.writeStringToFile(file, str);
//编译
//拿到当前系统的编译器
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//创建文件的管理者(参数1.诊断监听器 2.3国际化参数 简单起见设为null)
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null,null,null);
//获取文件(根据文件名得到管理文件的宿主)
Iterable units = fileManager.getJavaFileObjects(filename);
//编译任务 返回编译的一个任务
JavaCompiler.CompilationTask t = compiler.getTask(null, fileManager, null, null, null, units);
//将生成的$Proxy0进行编译等同javac命令
t.call();
fileManager.close();
//编译好的文件load到内存
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
Class c = classLoader.loadClass("com.demo.proxy.$Proxy0");
//根据构造器初始化 产生代理类并返回
Constructor constructor = c.getConstructor(InvocationHandler.class);
return constructor.newInstance(h);
}
}
//拷贝模仿的源代码类(代理类)
public class CarTimeProxy implements Moveable {
private Moveable moveable;
public CarTimeProxy(Moveable moveable) {
super();
this.moveable = moveable;
}
@Override
public void move() {
long startTime = System.currentTimeMillis();
System.out.println("汽车开始行驶---》");
moveable.move();
long endTime = System.currentTimeMillis();
System.out.println("汽车结束行驶。。。行驶时间:" + (endTime - startTime) + "ms!");
}
}
//事务处理器接口代码(InvocationHandler)
//事务处理器(newProxyInstance中使用)
public interface InvocationHandler {
void invoke(Object o, Method method);
}
//事务处理器实现类代码
代理类并不能做具体的事,声明一个Handler,由它接管实际的工作,具体业务在Handler中实现
//事务处理器实现类
public class TimeHandler implements InvocationHandler {
//被代理对象(调用方法)
private Object targer;
public TimeHandler(Object targer) {
super();
this.targer = targer;
}
//参数o 代理对象 其实调用的是被代理对象(通过构造方法初始化)
@Override
public void invoke(Object o, Method method) {
try {
long startTime = System.currentTimeMillis();
System.out.println("汽车开始行驶---》");
method.invoke(targer);
long endTime = System.currentTimeMillis();
System.out.println("汽车结束行驶。。。行驶时间:" + (endTime - startTime) + "ms!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
//测试类代码
public class TestProxy {
public static void main(String[] args) throws Exception {
//new Car()为被代理对象 moveable为代理对象
InvocationHandler invocationHandler = new TimeHandler(new Car());
Moveable moveable = (Moveable) Proxy.newProxyInstance(Moveable.class, invocationHandler);
moveable.move();
}
/*
Car类被代理前:
汽车开始行驶!
*/
/*
Car类被代理后:
汽车开始行驶---》
汽车开始行驶!
汽车结束行驶。。。行驶时间:0ms!
*/
}