一、什么是代理
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
代理模式UML图:
image.png
二、静态代理与动态代理的区别
静态代理中的代理类是需要用户自己写的,这样代理类在程序运行前就已经存在了。
动态代理中的代理类是在程序运行中自动生成的。
三、静态代理
// 接口
public interface Fruit {
void eat();
}
// 实现类
public class Apple implements Fruit {
public void eat() {
System.out.println("吃苹果");
}
}
// 代理类
public class AppleProxy implements Fruit {
private Apple apple;
public AppleProxy (Apple apple) {
this.apple = apple;
}
public void eat() {
System.out.println("吃前先洗手");
apple.eat();
System.out.println("吃后也洗手");
}
public static void main(String[] args) {
AppleProxy appleProxy = new AppleProxy(new Apple());
appleProxy.eat();
}
}
输出
吃前先洗手
吃苹果
吃后也洗手
四、JDK动态代理
// 实现类
public class Apple implements Fruit {
@Override
public void eat() {
System.out.println("吃苹果");
}
}
// 代理类
public class AppleProxy implements InvocationHandler {
public Object object;
public Object newProxy(Object object) {
this.object = object;
return Proxy.newInstance(object.getClass().getClassLoader(),
object.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("执行方法之前");
result = method.invoke(object, args);
System.out.println("执行方法之后");
return result;
}
}
// 客户端
public class Client {
public static void main(String[] args) {
AppleProxy appleProxy = new AppleProxy();
Fruit fruitProxy = (Fruit) appleProxy.newProxy(new Apple());
fruitProxy.eat();
}
}
输出
执行方法之前
吃苹果
执行方法之后
JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用CGLIB动态代理了
五、CGLIB动态代理
// 接口
public interface Fruit {
void eat();
}
// 实现类
public class Apple implements Fruit {
public void eat() {
System.out.println("吃苹果");
}
}
// 代理类
public class AppleProxy implements MethodInterceptor {
private Object object;
public Object getInstance(Object object) {
this.object = object;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.object.getClass());
//回调方法
enhancer.setCallback(this);
//创建代理对象
return enhancer.create();
}
public Object intercept(Object object, Method method,
Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("执行方法之前");
methodProxy.invokeSuper(object, args);
System.out.println("执行方法之后");
return null;
}
}
// 客户端
public class Client {
public static void main(String[] args) {
AppleProxy appleProxy = new AppleProxy();
Apple apple = (Apple) appleProxy.getInstance(new Apple());
apple.eat();
}
}
输出
执行方法之前
吃苹果
执行方法之后