https://gitee.com/xuhx615/AOPDemo.git
增强或拦截方法的调用
public interface Point {
/**
* 代理方法前调用
* @param args 代理方法的参数
* @return true放行;false拦截
*/
boolean before(Object[] args);
/**
* 代理方法后调用
* @param result 代理方法返回值
* @param e 代理方法抛出的异常
* @param args 代理方法的参数
*/
void after(Object result, Exception e,Object[] args);
}
import cn.com.jdk.point.Point;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
public class ActiveProxy implements InvocationHandler {
/**
* 切点
*/
private Point point;
/**
* 代理对象
*/
private Object obj;
/**
* 需要增强的方法
*/
private List<String> enhanceMethodList;
/**
* 是否全部增强
*/
private boolean isAllEnhance = true;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
Exception exception = null;
/**
* 判断
* 是否全部增强
* 如果不是全部增强,增强方法是否属于指定的方法
*/
if (isAllEnhance || (!isAllEnhance && !CollectionUtils.isEmpty(enhanceMethodList)
&& enhanceMethodList.contains(method.getName()))) {
boolean flag = point.before(args);
if(flag){
try {
result = method.invoke(obj, args);
} catch (Exception e) {
e.printStackTrace();
exception = e;
}
point.after(result, exception, args);
}
}else{
result = method.invoke(obj, args);
}
return result;
}
/**
* 创建代理对象
* @param clazz 代理对象的接口类clazz
* @param obj 代理对象实例
* @param point 切点实例
* @param
* @return
*/
public <T> T createObj(Class<T> clazz,T obj,Point point){
this.obj = obj;
this.point = point;
T t = (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, this);
return t;
}
public <T> T createObj(Class<T> clazz,T obj,Point point,boolean isAllEnhance,List<String> enhanceMethodList){
this.isAllEnhance = isAllEnhance;
this.enhanceMethodList = enhanceMethodList;
return createObj(clazz,obj,point);
}
}
import cn.com.cglib.point.Point;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Method;
import java.util.List;
public class ProxyMethodInterceptor implements MethodInterceptor {
private Point point;
private Object obj;
private List<String> enhanceMethodList;
private boolean isAllEnhance = true;
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result = null;
Exception exception = null;
if (isAllEnhance || (!isAllEnhance && !CollectionUtils.isEmpty(enhanceMethodList) && enhanceMethodList.contains(method.getName()))) {
boolean flag = point.before(objects);
if(flag){
try {
result = methodProxy.invoke(obj, objects);
} catch (Exception e) {
exception = e;
}
point.after(result,exception, objects);
}
}else{
result = methodProxy.invoke(obj, objects);
}
return result;
}
public <T> T createObj(T obj,Point point){
this.point = point;
this.obj = obj;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback(this);
T t = (T) enhancer.create();
return t;
}
public <T> T createObj(T obj,Point point,boolean isAllEnhance,List<String> enhanceMethodList){
this.isAllEnhance = isAllEnhance;
this.enhanceMethodList = enhanceMethodList;
return createObj(obj,point);
}
}
jdk
动态代理代理类实现的是java.lang.reflect.InvocationHandler
,cglib
动态代理代理类实现的是org.springframework.cglib.proxy.MethodInterceptor
。jdk
动态代理代理类使用的核心类是java.lang.reflect.Proxy
,cglib
动态代理使用的核心类是org.springframework.cglib.proxy.MethodProxy
jdk
动态代理代理对象必须有对应的接口和实现类,cglib
动态代理代理对象则是针对类,不需要有对应的接口。JDK
动态代理是实现了被代理对象的接口,Cglib
是继承了被代理对象。JDK
和Cglib
都是在运行期生成字节码,JDK
是直接写Class
字节码,Cglib
使用ASM框架写Class
字节码,Cglib
代理实现更复杂,生成代理类比JDK
效率低。JDK
调用代理方法,是通过反射机制调用,Cglib
是通过FastClass
机制直接调用方法,Cglib
执行效率更高。增强类:
import cn.hutool.aop.aspects.SimpleAspect;
import java.lang.reflect.Method;
public class TargetAspect extends SimpleAspect {
@Override
public boolean before(Object target, Method method, Object[] args) {
System.out.println("before");
return true;
}
@Override
public boolean after(Object target, Method method, Object[] args, Object returnVal) {
System.out.println("after");
return super.after(target, method, args, returnVal);
}
@Override
public boolean afterException(Object target, Method method, Object[] args, Throwable e) {
System.out.println("afterException");
return super.afterException(target, method, args, e);
}
}
调用:
import cn.hutool.aop.ProxyUtil;
TargetDemo proxy = ProxyUtil.proxy(new TargetDemoImpl(), new TargetAspect());
proxy.eat("鱼");
注意: 如果项目中没有引入cglib
依赖,那么ProxyUtil.proxy
的返回值类型必须是代理类的接口类型
,因为他走的是jdk动态代理
。
Spring AOP
的底层实现是cglib
动态代理。
Spring AOP
请点击该博客浏览:https://blog.csdn.net/qq_34191426/article/details/125223508