JDK的动态代理只允许代理接口
重要的类和接口Proxy和InvocationHandler
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)方法创建目标对象的代理对象
获取到目标对象的代理对象之后,执行目标对象的方法实际上是通过调用代理对象的invoke方法实现的
我们可以在invoke方法中增加额外的通用的逻辑来对目标对象进行增强
/** * @Description 代理对象 */ public class ProxyHandler implements InvocationHandler{ private Object target; public Object getProxyHandler(Object target){ this.target = target; Object o = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); return o; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before"); Object invoke = method.invoke(target, args); System.out.println("After"); return invoke; } }
获取到代理对象之后,像调用目标对象一样调用代理对象的方法,直观上和普通的调用没有任何区别,但是实际上调用的是代理对象的invoke方法,在invoke方法里面可以做的事情有很多,可以增强甚至重写某些方法,通过method.getName()来对指定方法进行处理
public class ProxyHandlerTest extends TestInit { @Autowired ISalesOrderFlowDomainService salesOrderFlowDomainService; @Test public void test(){ ProxyHandler proxyHandler = new ProxyHandler(); ISalesOrderFlowDomainService iSalesOrderFlowDomainService = (ISalesOrderFlowDomainService) proxyHandler.getProxyHandler(salesOrderFlowDomainService); SalesOrderFlowDTO salesOrderFlow = iSalesOrderFlowDomainService.getSalesOrderFlow("20210702000001", OrderFlowType.SIGNED); System.out.println(salesOrderFlow); } }
Cglib不是jdk自带的jar包,需要下载并加入到项目中
CGLIB代理相关的类:
CGLIB动态代理的原理就是用Enhancer生成一个原有类的子类,并且设置好callback到proxy, 则原有类的每个方法调用都会转为调用实现了MethodInterceptor接口的proxy的intercept() 函数
public class CglibProxy implements MethodInterceptor{ //主要的增强类。 private Enhancer enhancer = new Enhancer(); @Override /** * * @param o 是被代理对象 * @param method 调用方法的Method对象 * @param args 方法参数 * @param methodProxy * @return cglib生成用来代替Method对象的一个对象,使用MethodProxy比调用JDK自身的Method直接执行方法效率会有提升 * @throws Throwable */ public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("before " + methodProxy.getSuperName()); System.out.println(method.getName()); Object o1 = methodProxy.invokeSuper(o, args); //Object o2 = method.invoke(o, args); 使用这种方式会发生死循环,因为方法会被拦截 System.out.println("after " + methodProxy.getSuperName()); return o1; } public Object newProxyInstance(Class<?> c) { //设置产生的代理对象的父类。 enhancer.setSuperclass(c); //设置CallBack接口的实例 enhancer.setCallback(this); //使用默认无参数的构造函数创建目标对象 return enhancer.create(); } }
public class CglibDemo { public static void main(String[] args) { CglibProxy cglibProxy = new CglibProxy(); Do o = (Do)cglibProxy.newProxyInstance(Do.class); System.out.println(o.doSomething(5)); } } class Do{ public int doSomething(int num){ System.out.println("方法执行中。。。。。。"); return num; } }
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
【参考文章】
【1】https://www.cnblogs.com/shijiaqi1066/p/3429691.html