1. 什么是代理模式
代理模式是常见的设计模式之一,顾名思义,代理模式就是代理对象具备真实对象的功能,并代替真实对象完成相应操作,并能够在操作执行的前后,对操作进行增强处理。(为真实对象提供代理,然后供其他对象通过代理访问真实对象)。
代理就是帮别人做事情,如:工厂的中介,中介负责为工厂招收工人,那么中介就是工厂的代理;客户通过商家购买东西,商家向厂家购买货物,商家就是工厂的代理 。
在开发中存在a类需要调用c类的方法,完成某一个功能,但是c禁止a调用。这时,可以在a和c之间创建一个b类代理,a类访问b类,b类访问c类。
代理模式就是为其他对象提供一种代理来控制这个对象的访问,在某些情况下一个对象不适合或不能直接引用另一个对象,而代理对象可以在客户类和目标对象直接起到中介的作用
代理有分为动态代理和静态代理
2. 什么是静态代理
由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口,被代理类,代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成.
缺点:
1. 被代理对象增加,代理对象也要增加,导致代理数量过多
2. 被代理对象接口如有改动,其实现类都需要改动
/**
* 订单接口类
*/
public interface OrderService {
void save();
}
/**
* 订单实现类
*/
public class OrderServiceImpl implements OrderService{
@Override
public void save() {
System.out.println("保存订单信息 ...");
}
}
/**
* 代理对象
*/
public class ProxyOrderService implements OrderService {
// 被代理的对象
private OrderService orderService;
public ProxyOrderService(OrderService orderService) {
this.orderService = orderService;
}
@Override
public void save() {
System.out.println("代理前置处理 ...");
// 执行被代理的对象的方法
orderService.save();
System.out.println("代理后置处理 ...");
}
}
// 执行
public static void main(String[] args) {
// 创建被代理对象
OrderService orderService = new OrderServiceImpl();
// 创建代理对象
ProxyOrderService proxy = new ProxyOrderService(orderService);
proxy.save();
}
输出
2. 什么是动态代理
代理类在程序运行时创建的代理方式被成为动态代理。 我们上面静态代理的例子中,代理类(ProxyOrderService )是自己定义好的,在程序运行之前就已经编译完成。然而动态代理,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。
jdk 动态代理
/**
* 订单接口类
*/
public interface OrderService {
void save();
}
/**
* 订单实现类
*/
public class OrderServiceImpl implements OrderService{
@Override
public void save() {
System.out.println("保存订单信息 ...");
}
}
/**
*
* 代理对象 实现 InvocationHandler
* InvocationHandler 该类做方法拦截所用, 通过此类可以对目标方法进行增强
*/
public class ProxyOrderService implements InvocationHandler {
private OrderService orderService;
public ProxyOrderService(OrderService orderService) {
this.orderService = orderService;
}
/**
* 通过该方法的调用对目标对象进行增强
* @param proxy 代理类代理的真实代理对象
* @param method 执行的方法
* @param args 执行方法的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理前置处理 ...");
Object invoke = method.invoke(orderService, args);
System.out.println("代理后置处理 ...");
return invoke;
}
/**
* ClassLoader loader 类加载器
* Class<?>[] interfaces 代理对象类类型
* InvocationHandler 处理类
*
* @param args
*/
public static void main(String[] args) {
ProxyOrderService proxyOrderService = new ProxyOrderService(new OrderServiceImpl());
// 返回代理对象
OrderService orderService =
(OrderService) Proxy
.newProxyInstance(ProxyOrderService.class.getClassLoader(), new Class[]{OrderService.class}, proxyOrderService);
orderService.save();
}
}
执行结果
代理类源码
生成的代理类源码方法
/**
* 生成动态代理源码
*
* @param path 保存路径
* @param var1 代理对象类类型
*/
private static void saveProxyClass(String path, Class<?>[] var1) {
byte[] $proxy1s = ProxyGenerator.generateProxyClass("$Proxy1", var1);
FileOutputStream out = null;
try {
out = new FileOutputStream(new File(path + "$Proxy1.class"));
out.write($proxy1s);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
cglib 代理
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.7</version>
</dependency>
/**
* 订单接口类
*/
public interface OrderService {
void save();
}
/**
* 订单实现类
*/
public class OrderServiceImpl implements OrderService{
@Override
public void save() {
System.out.println("保存订单信息 ...");
}
}
/**
* 实现 MethodInterceptor 重写 intercept
*
*/
public class MyInterceptor implements MethodInterceptor {
/**
*
* @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("cglib代理方法执行之前 ...");
Object o1 = methodProxy.invokeSuper(o, objects);
System.out.println("cglib代理方法执行之后 ...");
return o1;
}
}
public static void main(String[] args) {
// 代理类class文件存入本地磁盘方便我们反编译查看源码
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./code");
// 通过CGLIB动态代理获取代理对象的过程
Enhancer enhancer = new Enhancer();
// 设置enhancer对象的父类
enhancer.setSuperclass(OrderServiceImpl.class);
// 设置enhancer的回调对象
enhancer.setCallback(new MyInterceptor());
// 创建代理对象
OrderService orderService = (OrderServiceImpl) enhancer.create();
orderService.save();
}
运行结果
Java动态代理和cglib比较
生成代理类技术不同
java动态代理:jdk自带类ProxyGenerator生成class字节码
cglib:通过ASM框架生成class字节码文件
生成代理类的方式不同
java动态代理:代理类继承java.lang.reflect.Proxy,实现被代理类的接口
cglib:代理类继承被代理类,实现net.sf.cglib.proxy.Factory
生成类数量不同
java动态代理:生成一个proxy类
cglib:生成一个proxy,两个fastclass类
调用方式不同
java动态代理:代理类->InvocationHandler->反射调用被代理类方法
cglib:代理类->MethodInterceptor->调用索引类invoke->直接调用被代理类方法