代理模式的定义: 为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可以去掉功能服务或者添加额外的服务
静态代理: 代理和被代理对象在代理之前是确定的。他们都实现相同的接口或者继承相同的抽象类
UML图:
以聚合代理的方式实现静态代理为例:
首先抽象接口
package proxy;
public interface Moveable {
void move();
}
package proxy;
import java.util.Random;
public class Car implements Moveable {
public void move() {
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶.....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
代理类1:
package proxy;
public class CarLogProxy implements Moveable {
public CarLogProxy(Moveable m) {
super();
this.m = m;
}
private Moveable m;
public void move() {
System.out.println("Log开始");
m.move();
System.out.println("Log结束");
}
}
package proxy;
public class CarTimeProxy implements Moveable {
public CarTimeProxy(Moveable m) {
super();
this.m = m;
}
private Moveable m;
public void move() {
System.out.println("计时开始");
m.move();
System.out.println("计时结束");
}
}
package proxy;
public class Client {
public static void main(String[] args) {
Car car = new Car();
CarLogProxy clp = new CarLogProxy(car);
CarTimeProxy ctp = new CarTimeProxy(clp);
ctp.move();
}
}
运行结果:
计时开始
Log开始
汽车行驶.....
Log结束
计时结束
但静态代理只能代理一种类型的被代理类,换个类型的就不行了,这需要动态代理
Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:
(1)Interface InvocationHandler : 该接口中定义了一个方法
public object invoke(Object obj , Method method , Object[] args)
在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。
(2) Proxy : 该类即为动态代理类
static Object newProxyInstance(ClassLoader loader , Class[] interfaces , InvocationHandler h) : 返回代理类的一个实例, 返回后的代理类可以当作被代理类使用
动态代理实现步骤
(1)创建一个实现接口InvocationHandler的类,它必须实现invoke方法
(2)创建被代理的类以及接口
(3)调用Proxy的静态方法,创建一个代理类
newProxyInstance(ClassLoader loader , Class[] interfaces , InvocationHandler h)
(4) 通过代理调用方法
例:抽象接口
package proxy;
public interface Moveable {
void move();
}
被代理类:
package proxy;
import java.util.Random;
public class Car implements Moveable {
public void move() {
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
InvocationHandler 实现类
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TimeHandler implements InvocationHandler {
public TimeHandler(Object target) {
super();
this.target = target;
}
private Object target;
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("计时前");
method.invoke(target);
System.out.println("计时后");
return null;
}
}
测试:
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import proxy.Car;
import proxy.Moveable;
public class Test {
public static void main(String[] args) {
Car car = new Car();
InvocationHandler h = new TimeHandler(car);
Class<?> cls = car.getClass();
Moveable m = (Moveable)Proxy.newProxyInstance(cls.getClassLoader(),
cls.getInterfaces(), h);
m.move();
}
}
运行结果:
计时前
汽车行驶....
计时后
除了使用JDK实现动态代理之外,还可以使用CGLIB实现 ,需要引入cglib的jar包
被代理类:
package cglibproxy;
public class Train {
public void move(){
System.out.println("汽车行驶...");
}
}
代理类:
package cglibproxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
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;
}
}
测试:
package cglibproxy;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
Train t = (Train)proxy.getProxy(Train.class);
t.move();
}
}
运行结果:
代理开始..
汽车行驶...
代理结束...
两种动态代理的区别
JDK动态代理:
(1) 只能代理实现了接口的类;
(2)没有实现接口的类不能实现JDK的动态代理。
CGLIB动态代理:
(1) 针对类来实现代理的;
(2)对指定目标类产生一个子类, 通过方法拦截技术拦截所有的父类方法的调用。