cglib在动态代理时,无法像jdk动态代理那样对代理对象再次执行代理。
问题原理分析参考博客CGLIB-多重代理
整合自己的手写spring
在进行动态代理时,如果该类有接口,则进行jdk动态代理,如果没有接口,则取执行cglib的动态代理逻辑,其中jdk动态代理过程如下:
private Object jdkDynamicProxy(Class<?> clazz, Object bean) {
for (AopProcessor aopProcessor : aopProcessors) {
String pointCut = aopProcessor.getPointCut();
if (BeanUtils.aopMatch(pointCut, clazz.getName())) {
JdkDynamicProxy jdkDynamicProxy = new JdkDynamicProxy(bean, aopProcessor);
//如果有接口,使用jdk动态代理
bean = jdkDynamicProxy.getProxyBean();
}
}
return bean;
}
直接对bean进行反复代理和赋值即可。
对于cglib代理来说,则需要使用责任链模式,将aop类封装成责任链执行者,然后在代理类中执行该责任链即可,实现代码如下:
定义调用链方法:
public interface CglibPoint {
//处理代理对象的代理功能,是责任链的调用链方法
Object proceed(CglibChain chain, Method method, Object[] args);
}
定义责任链对象
public class CglibChain {
//切面链
private List<CglibPoint> cglibPoints;
//责任链开始的位置
private int idx = -1;
//被代理对象
private Object target;
public CglibChain(Object target) {
this.target = target;
this.cglibPoints = new ArrayList<>();
}
public void registCglibPoint(CglibPoint cglibPoint) {
cglibPoints.add(cglibPoint);
}
/**
* 执行代理链
* @param method 被代理方法
* @param args 被代理方法参数
* @return
*/
public Object process(Method method, Object[] args) {
Object res = null;
//没有责任链了就直接返回
if (++idx ==cglibPoints.size()){
try {
res = method.invoke(target, args);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
// System.out.println("cglib代理结束");
}else {
res = cglibPoints.get(idx).proceed(this, method, args);
}
return res;
}
public void resetIdx() {
this.idx = -1;
}
}
代理类对象
public class CglibProxy implements MethodInterceptor {
//被代理类
private Object target;
//由于cglib不能多重代理,所以将所有的代理功能放在一个责任链中执行
private CglibChain cglibChain;
public CglibProxy(Object target) {
this.target = target;
this.cglibChain = new CglibChain(target);
}
/**
* 将aop方法转化为责任链并注册到责任链对象中
* @param aopProcessor aop类
*/
public void registCglibPoint(AopProcessor aopProcessor) {
cglibChain.registCglibPoint(new CglibPoint() {
@Override
public Object proceed(CglibChain chain, Method method, Object[] args) {
Object res = null;
try {
Object newInstance = aopProcessor.getClazz().getConstructor().newInstance();
//将切面信息包装成ProceedingJoinPoint对象
ProceedingJoinPoint joinPoint = new ProceedingJoinPoint();
joinPoint.load(target);
//增强前方法
Method beforeMethod = aopProcessor.getBeforeMethod();
if (beforeMethod != null) beforeMethod.invoke(newInstance,joinPoint);
//执行本方法
res = chain.process(method, args);
//增强后方法
Method afterMethod = aopProcessor.getAfterMethod();
if (afterMethod != null) afterMethod.invoke(newInstance,joinPoint);
} catch (Exception e) {
throw new RuntimeException(e);
}
return res;
}
});
}
/**
* 获取代理对象
* @return
*/
public Object getProxyBean() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
Object o = enhancer.create();
return o;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
cglibChain.resetIdx();
return cglibChain.process(method, objects);
}
}
AOP部分代码:
/**
* cglib无法多重代理,需要转换为拦截器链模式来实现
*
* @param clazz
* @param bean
* @return
*/
private Object cglibProxy(Class<?> clazz, Object bean) {
//没有接口用cglib
CglibProxy cglibProxy = new CglibProxy(bean);
//注册所有的Aop,因为cglib不能多重代理
for (AopProcessor aopProcessor : aopProcessors) {
String pointCut = aopProcessor.getPointCut();
if (BeanUtils.aopMatch(pointCut, clazz.getName())) {
cglibProxy.registCglibPoint(aopProcessor);
}
}
bean = cglibProxy.getProxyBean();
return bean;
}
结果: