代理模式
代理模式是一种结构型设计模式,它允许你提供一个代理对象来控制对另一个对象的访问。代理模式可以在不改变原始对象的情况下,增强或控制对原始对象的访问。代理模式通常用于延迟加载、访问控制、日志记录、性能监控等场景。
1.静态代理
静态代理是指在编译时就已经确定代理类和被代理类的关系。静态代理通常需要手动编写代理类,并且代理类和被代理类实现相同的接口或继承相同的父类
java
public interface OrderService {
void save();
}
public class ProxyOrderService implements OrderService {
// 被代理的对象
private OrderService orderService;
public ProxyOrderService(OrderService orderService) {
this.orderService = orderService;
}
// 执行
public static void main(String[] args) {
// 创建被代理对象
OrderService orderService = new OrderServiceImpl();
// 创建代理对象
ProxyOrderService proxy = new ProxyOrderService(orderService);
proxy.save();
}
@Override
public void save() {
System.out.println("代理前置处理 ...");
// 执行被代理的对象的方法
orderService.save();
System.out.println("代理后置处理 ...");
}
}
2 动态代理
动态代理是指在运行时动态生成代理类,而不是在编译时手动编写代理类。
2.1 JDK动态代理
JDK动态代理基于Java反射机制实现,它需要被代理对象实现一个接口。
java
/**
* 代理对象 实现 InvocationHandler
* InvocationHandler 该类做方法拦截所用, 通过此类可以对目标方法进行增强
*/
public class JDKProxyDynamic implements InvocationHandler, Serializable {
private static final long serialVersionUID = 4431939583048226878L;
private Object target;
private Class<?> clazz;
public JDKProxyDynamic(Class<?> clazz) {
this.clazz = clazz;
}
/**
* 通过该方法的调用对目标对象进行增强
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调度真实对象之前,方法名: " + method.getName() + ",参数:" + args);
// Spring框架中使用动态代理,可以从applicationContext里面获取对应的target对象
if (Objects.isNull(target)) {
target = clazz.newInstance();
}
System.out.println("代理前置处理 ...");
Object returnResult = method.invoke(target, args);
System.out.println("代理后置处理 ...");
return returnResult;
}
public static void main(String[] args) {
// 创建动态代理对象,JDK动态代理只能代理实现接口的类
OrderService proxyInstance = (OrderService) Proxy.newProxyInstance(
OrderServiceImpl.class.getClassLoader(),
OrderServiceImpl.class.getInterfaces(),
new JDKProxyDynamic(OrderServiceImpl.class)
);
// 通过代理对象调用方法
proxyInstance.save();
}
}
2.2 CGLIB动态代理
CGLIB动态代理基于ASM字节码生成框架实现,它不需要被代理对象实现接口。CGLIB动态代理是针对类进行代理的,它通过继承目标类创建子类,并重写目标类的方法。
java
public class CglibProxy implements MethodInterceptor {
private static CglibProxy INSTANCE = new CglibProxy();
private Object target;
private Class<?> clazz;
private CglibProxy() {
}
public CglibProxy(Class<?> clazz) {
this.clazz = clazz;
}
public static CglibProxy getInstance() {
return INSTANCE;
}
public Object getCglibProxyObject(Object target) {
// 可以在Spring中获取指定对象,为其创建代理对象,再指定对应的target
this.clazz = target.getClass();
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
/**
* @param object 被代理的对象
* @param method 被代理对象需要执行的方法
* @param args 被代理对象需要执行的方法 参数
* @param proxy 触发父类的方法对象
* @return 被代理对象需要执行的方法 返回值
* @throws Throwable 抛出的异常信息
*/
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method execution: " + method.getName());
Object result = proxy.invokeSuper(object, args);
System.out.println("After method execution: " + method.getName());
return result;
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OrderServiceImpl.class);
enhancer.setCallback(new CglibProxy());
OrderService orderService = (OrderService) enhancer.create();
orderService.save();
}
}