定义
- 为其他对象提供一种代理以控制对这个对象的访问
- 代理对象起到中介服务,可以去掉和新增服务
静态代理
- 代理和被代理的对象在代理之前是确定的,他们都实现相同的接口或继承相同的类
/**
* 定义汽车行驶接口
*/
public interface Moveable {
void move();
}
/**
* 定义汽车实现接口
*/
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 class CarExtends extends Car {
@Override
public void move() {
long start = System.currentTimeMillis();
System.out.println("开始行驶...");
//实现对car的代理
super.move();
System.out.println("结束行驶...");
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start));
}
public static void main(String[] args) {
Moveable m = new CarExtends();
m.move();
}
}
运行结果:
开始行驶...
行驶中...
结束行驶...
用时:154
聚合方式实现代理(推荐)
/**
* 聚合方式实现代理
*/
public class CarTimeProxy implements Moveable {
private Moveable m;
public CarTimeProxy(Moveable m) {
this.m = m;
}
@Override
public void move() {
long start = System.currentTimeMillis();
System.out.println("开始行驶...");
//实现对car的代理
m.move();
System.out.println("结束行驶...");
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start));
}
public static void main(String[] args) {
Moveable m = new CarTimeProxy(new Car());
m.move();
}
}
运行结果:
开始行驶...
行驶中...
结束行驶...
用时:856
代理功能的叠加
/**
* 日志代理
* 模拟日志和时间 功能的叠加
*/
public class CarLogProxy implements Moveable {
private Moveable m;
public CarLogProxy(Moveable m) {
this.m = m;
}
@Override
public void move() {
System.out.println("日志开始...");
//实现对car的代理
m.move();
System.out.println("日志结束...");
}
public static void main(String[] args) {
Car car = new Car();
//先记录时间在记录日志
System.out.println("==================先记录时间再记录日志====================");
CarLogProxy carLogProxy = new CarLogProxy(car);
CarTimeProxy carTimeProxy = new CarTimeProxy(carLogProxy);
carTimeProxy.move();
System.out.println("==================先记录日志再记录时间====================");
CarTimeProxy carTimeProxy1 = new CarTimeProxy(car);
CarLogProxy carLogProxy1 = new CarLogProxy(carTimeProxy1);
carLogProxy1.move();
}
}
//注意:如果用继承方式,这里实现两种情况就需要两个类来继承car,显然不方便
//这里只是汽车,如果现在有火车自行车也许要时间和日志功能,怎么办,使用动态代理
动态代理
JDK动态代理
- 如图所示,动态代理就是在代理类(ProxySubject)和被代理类(RealSubject)之间加了一个的事务处理器(InvocationHandler)
- InvocationHandler位于java.lang.reflect
/**
*
* @param proxy 代理类
* @param method 被代理方法
* @param args 方法参数
* @return 被代理方法返回值
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
- Proxy:动态代理类
/**
* @param loader 被代理类的类加载器
* @param interfaces 被代理类的实现接口
* @param h InvocationHandler
* @return 返回代理类的一个实例
* @throws IllegalArgumentException
*/
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException
jdk动态代理实现
import com.interview.proxy.Car;
import com.interview.proxy.Moveable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class TimeHandler implements InvocationHandler {
private Object target;
public TimeHandler(Object target) {
this.target = target;
}
/**
* @param proxy 被代理对象
* @param method 被代理对象方法
* @param args 方法参数
* @return 被代理方法返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.currentTimeMillis();
System.out.println("开始行驶...");
//有参数和返回值时
// Object obj = method.invoke(target, args);
method.invoke(target);
System.out.println("结束行驶...");
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start));
return null;
}
public static void main(String[] args) {
Car car = new Car();
InvocationHandler h = new TimeHandler(car);
Class<?> clazz = car.getClass();
ClassLoader c = clazz.getClassLoader();
Moveable m = (Moveable) Proxy.newProxyInstance(c, clazz.getInterfaces(), h);
m.move();
}
}
cglib动态代理
引入jar包
public class Train {
public void move(){
System.out.println("火车行驶中...");
}
}
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
/**
* 获取代理类
* @param clazz
* @return
*/
public Object getProxy(Class clazz) {
//设置创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
/**
* 拦截所有目标类方法的调用
* @param o 目标类实例
* @param method 目标方法反射对象
* @param objects 方法参数
* @param methodProxy 代理类实例
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("日志开始...");
//代理类调用父类的方法
Object obj = methodProxy.invokeSuper(o, objects);
System.out.println("日志结束...");
return obj;
}
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
Train train = (Train) cglibProxy.getProxy(Train.class);
train.move();
}
}
JDK动态代理和cglib动态代理区别
- JDK动态代理只能代理实现了接口的类
- cglib动态代理针对类来实现,对制定目标产生一个子类,通过方法拦截技术拦截所有的父类方法的调用