场景
众说周知cglib实现的代理只能被代理一次,二次代理就会抛出异常,然而Spring Aop却可以对一个方法多次拦截。这里面用了什么黑科技呢,让我们一起来看看吧
依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
被代理对象
/**
* @author caohu
* @version 1.0
* @date 2022/2/21 10:14 AM
*/
public class OrderService {
private Object orderDao;
public String getOrder(Long id) {
System.out.println("获取了订单" + id);
return "order" + id;
}
public void addOrder(Long id) {
System.out.println("添加了订单" + id);
}
public void setOrderDao(Object orderDao) {
this.orderDao = orderDao;
}
public Object getOrderDao() {
return this.orderDao;
}
}
定义拦截器接口
import java.lang.reflect.Method;
/**
* @author caohu
* @version 1.0
* @date 2022/2/23 6:47 PM
*/
public interface ProxyInterceptor {
/**
* 是否拦截
* @param target
* @param args
* @param method
* @return
*/
default boolean accept(Object target, Object[] args, Method method) {
return true;
}
/**
* 代理执行
* @param target
* @param args
* @param method
* @param proxyInterceptorChain
* @return
* @throws Throwable
*/
Object invoke(Object target, Object[] args, Method method, ProxyInterceptorChain proxyInterceptorChain) throws Throwable;
}
定义拦截器链
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.util.List;
/**
* @author caohu
* @version 1.0
* @date 2022/2/24 4:02 PM
*/
public class ProxyInterceptorChain {
private int i;
private List<ProxyInterceptor> proxyInterceptors;
private MethodProxy methodProxy;
public ProxyInterceptorChain(List<ProxyInterceptor> proxyInterceptors, MethodProxy methodProxy) {
i = proxyInterceptors.size();
this.proxyInterceptors = proxyInterceptors;
this.methodProxy = methodProxy;
}
public Object chain(Object target, Object[] args, Method method) throws Throwable {
if (0 == i) {
return methodProxy.invokeSuper(target, args);
}
ProxyInterceptor proxyInterceptor = proxyInterceptors.get(--i);
if (!proxyInterceptor.accept(target, args, method)) {
return chain(target, args, method);
}
return proxyInterceptor.invoke(target, args, method, this);
}
}
代理工具类
import org.springframework.aop.SpringProxy;
import org.springframework.aop.support.AopUtils;
import org.springframework.cglib.proxy.CallbackHelper;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author caohu
* @version 1.0
* @date 2022/2/23 6:45 PM
*/
public class ProxyUtil {
private static final Map<Class<?>, List<ProxyInterceptor>> PROXY_INTERCEPTOR_CHAIN_MAP = new ConcurrentHashMap<>(16);
public static Object proxy(Object target, ProxyInterceptor proxyInterceptor) {
// 如果已经被代理过了 则只加入拦截器链中
if (AopUtils.isCglibProxy(target)) {
Class<?> clazz = target.getClass();
while (clazz != null) {
List<ProxyInterceptor> proxyInterceptors = PROXY_INTERCEPTOR_CHAIN_MAP.get(clazz);
if (null != proxyInterceptors) {
proxyInterceptors.add(proxyInterceptor);
return target;
}
clazz = clazz.getSuperclass();
}
throw new RuntimeException();
}
List<ProxyInterceptor> proxyInterceptors = new ArrayList<>();
proxyInterceptors.add(proxyInterceptor);
PROXY_INTERCEPTOR_CHAIN_MAP.put(target.getClass(), proxyInterceptors);
Class<?> clazz = target.getClass();
CallbackHelper callbackHelper = new CallbackHelper(clazz, new Class[0]) {
@Override
protected Object getCallback(Method method) {
return (MethodInterceptor) (o, method1, objects, methodProxy) -> {
ProxyInterceptorChain chain = new ProxyInterceptorChain(proxyInterceptors, methodProxy);
return chain.chain(o, objects, method1);
};
}
};
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallbackFilter(callbackHelper);
enhancer.setCallbacks(callbackHelper.getCallbacks());
// 标识为spring代理
enhancer.setInterfaces(new Class[]{SpringProxy.class});
// 原对象的字段值不会被保留
return enhancer.create();
}
}
代理测试
import com.ch.my.demo.proxy.service.OrderService;
import com.ch.my.demo.proxy.service.component.ProxyInterceptor;
import com.ch.my.demo.proxy.service.component.ProxyInterceptorChain;
import com.ch.my.demo.proxy.service.component.ProxyUtil;
import org.junit.Test;
import java.lang.reflect.Method;
/**
* @author caohu
* @version 1.0
* @date 2022/2/23 6:52 PM
*/
public class TestProxyUtil {
@Test
public void testProxyUtil() {
OrderService orderService = new OrderService();
// 被代理后原对象字段值不会保留
orderService.setOrderDao(new Object());
// 第一次代理
orderService = (OrderService) ProxyUtil.proxy(orderService, new ProxyInterceptor() {
@Override
public boolean accept(Object target, Object[] args, Method method) {
return args[0].equals(1L);
}
@Override
public Object invoke(Object target, Object[] args, Method method, ProxyInterceptorChain proxyInterceptorChain) throws Throwable {
System.out.println("orderService1-Before");
Object result = proxyInterceptorChain.chain(target, args, method);
System.out.println("orderService1-After");
return result;
}
});
//第二次代理
orderService = (OrderService) ProxyUtil.proxy(orderService, new ProxyInterceptor() {
@Override
public boolean accept(Object target, Object[] args, Method method) {
return args[0].equals(1L);
}
@Override
public Object invoke(Object target, Object[] args, Method method, ProxyInterceptorChain proxyInterceptorChain) throws Throwable {
System.out.println("orderService2-Before");
Object result = proxyInterceptorChain.chain(target, args, method);
System.out.println("orderService2-After");
return result;
}
});
orderService.getOrder(1L);
}
}
输出
orderService2-Before
orderService1-Before
获取了订单1
orderService1-After
orderService2-After