代理模式
定义:为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务。
平时讲的代理主要指的是智能引用代理,它又有两种实现方式:静态代理和动态代理。
静态代理:
代理和被代理对象在代理之前是确定的,他们都继承相同的抽象类或实现相同的接口。且一般都是使用聚合的方式来实现。
moveable接口
public interface Moveable {
void move();
}
Car类
public class Car implements Moveable {
@Override
public void move() {
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶中.....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
TimeProxy记录行驶时间代理类
public class TimeProxy implements Moveable {
private Moveable car;
public TimeProxy(Moveable car) {
super();
this.car = car;
}
@Override
public void move() {
long startime=System.currentTimeMillis();
System.out.println("汽车开始行驶");
car.move();
long endtime=System.currentTimeMillis();
System.out.println("汽车结束行驶,行驶时间:"+(endtime-startime)+"毫秒");
}
}
LogProxy记录日志代理类
public class LogProxy implements Moveable {
private Moveable car;
public LogProxy(Moveable car) {
super();
this.car = car;
}
@Override
public void move() {
System.out.println("开始记录日志");
car.move();
System.out.println("日志记录结束");
}
}
测试类
public class Client {
public static void main(String[] args) {
//使用聚合的方式实现的静态代理
Car car=new Car();
Moveable mt=new LogProxy(car);
Moveable m=new TimeProxy(mt);
m.move();
}
}
运行结果
JDK动态代理:只能代理实现了接口的类。
TimeHandler类(实现InvocationHandler接口)
public class TimeHandler implements InvocationHandler {
private Object target;
public TimeHandler(Object target) {
this.target=target;
}
/*
* 参数:
* proxy被代理对象
* method被代理对象的方法
* args方法的参数
*
* 返回值:
* Object 方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long startime=System.currentTimeMillis();
System.out.println("汽车开始行驶");
method.invoke(target);
long endtime=System.currentTimeMillis();
System.out.println("汽车结束行驶,行驶时间:"+(endtime-startime)+"毫秒");
return null;
}
}
测试类
public class Test {
//JDK动态代理测试类
public static void main(String[] args) {
Car car=new Car();
InvocationHandler h=new TimeHandler(car);
Class<?> cls=car.getClass();
/*
* loader:类加载器
* interfaces:被代理类实现的接口
* h:InvocationHandler对象(事务处理器)
*/
Moveable m=(Moveable)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h); //生成代理对象
m.move();
}
}
CGLIB动态代理:1.针对类来实现代理 2.对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。
首先你需要引入cglib-nodep-2.2.jar包
被代理类
public class Plane {
public void move(){
System.out.println("飞机飞行中......");
}
}
CglibProxy类
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer=new Enhancer();
//返回代理类对象
public Object getProxy(Class<?> cls){
//为cls创建子类代理类
enhancer.setSuperclass(cls);
enhancer.setCallback(this);
return enhancer.create();
}
/*
* 拦截所有目标类方法的调用
* 参数:
* obj 目标类的实例
* m 目标方法的反射对象
* args 方法的参数
* proxy 代理类的实例
*/
@Override
public Object intercept(Object obj, Method m, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("日志开始..");
//代理类调用父类的方法
proxy.invokeSuper(obj, args);
System.out.println("日志结束...");
return null;
}
}
测试类
public class Client {
public static void main(String[] args) {
CglibProxy proxy=new CglibProxy();
Plane p=(Plane) proxy.getProxy(Plane.class);
p.move();
}
}
JDK动态代理实现原理:
实现功能:通过Proxy的newProxyInstance方法返回代理对象
步骤:1.声明一段源码(动态产生代理) 2.编译源码(JDK Compiler API),产生新的类(代理类) 3.将此类load到内存中,产生一个新的对象(代理对象) 4.return代理对象
下面的代码是我在之前静态代理的基础上修改的。
Car类
public class Car implements Moveable {
@Override
public void move() {
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶中.....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
接口
public interface Moveable {
void move();
}
自定义的InvocationHandler接口
public interface InvocationHandler {
public void invoke(Object obj,Method m);
}
因为move方法没有参数,这里invoke的参数也就没加上"方法的参数"
TimeHandler类
public class TimeHandler implements InvocationHandler {
private Object target;
public TimeHandler(Object target) {
super();
this.target = target;
}
@Override
public void invoke(Object obj, Method m) {
try {
long startime=System.currentTimeMillis();
System.out.println("汽车开始行驶");
m.invoke(target);
long endtime=System.currentTimeMillis();
System.out.println("汽车结束行驶,行驶时间:"+(endtime-startime)+"毫秒");
} catch (Exception e) {
e.printStackTrace();
}
}
}
最重要的Proxy类
public class Proxy {
//infce为接口的Class对象
public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception{
String rt="\r\n"; //windows换行符
String methodStr="";
for(Method m:infce.getMethods()){
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){e.printStackTrace();}"+rt+
" }";
}
//1.声明一段源码
String str=
"package com.wulijian.staticproxy;"+rt+
"import com.wulijian.staticproxy.InvocationHandler;"+rt+
"import java.lang.reflect.Method;"+rt+
"public class $Proxy0 implements "+infce.getName()+"{"+rt+ //jdk生成的动态代理类名字是$Proxy0
" private InvocationHandler h;"+rt+
" public $Proxy0(InvocationHandler h) {"+rt+
" this.h = h;"+rt+
" }"+rt+
methodStr+rt+
"}";
//2.编译源码,产生代理类
//String filename=System.getProperty("user.dir"); 当前工程所在路径(F:\eclipse_workspace\Proxy)
String filename=System.getProperty("user.dir")+"/bin/com/wulijian/staticproxy/$Proxy0.java";
File file=new File(filename);
FileUtils.writeStringToFile(file, str);
//得到编译器
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);
//进行编译,生成.class文件
t.call();
fileMgr.close();
//3.将class文件load到内存中
ClassLoader cl=ClassLoader.getSystemClassLoader();
Class c=cl.loadClass("com.wulijian.staticproxy.$Proxy0");
Constructor ctr=c.getConstructor(InvocationHandler.class);
//得到反射类实例
return ctr.newInstance(h);
}
}
测试类
public class Client {
public static void main(String[] args) throws Exception {
Car car=new Car();
InvocationHandler h=new TimeHandler(car);
Moveable m=(Moveable) Proxy.newProxyInstance(Moveable.class,h);
m.move();
}
}