JDK动态代理VS CgLib
2016-04-21 18:09
966 查看
业务场景
描述:每个旅客乘坐火车时,在上车、下车之前需要检票。站在乘客的角度,这个过程可以看做一件事:检票坐车检票;也可以看做两件事:检票,坐车;站在检票员的角度,那就是一件事,检票。
如果我们用代码实现,可能是这样的过程:
checkTicket(); takingTrain(); checkTicket();
如果有一天,车站变成刷身份证进站了,我们就得回去改代码了... 下面我们将这个过程分开,用代理来解决坐车意外的问题: 业务逻辑:坐火车 额外需要:检票/刷卡
具体实现
- JDK动态代理,主要类、接口:Proxy, InvocationHandle,JDK动态代理特点只能对接口进行代理
所以需要一个业务逻辑接口:TakingTrain;
package com.spring.mybean; public interface TakingTrain { public void takeTrain(String name); }
实现类:TakingTrainImpl------>要被代理的目标类,实现TakingTrain接口
package com.spring.mybean.imp; import com.spring.mybean.TakingTrain; public class TakingTrainImpl implements TakingTrain { public void takeTrain(String name) { System.out.println("Hi "+name+ "Welcome to take the train"); } }
增强的横切逻辑:CheckTicket------>增强类,实现InvocationHandle接口
package com.spring.myadvice; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class CheckTicket implements InvocationHandler { private Object target; public CheckTicket(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("please show your tickes"); Object obj=method.invoke(target, args); return obj; } }
调用:
public class TakingTainingTest { @Test public void takingTrain(){ TakingTrain target=new TakingTrainImpl(); CheckTicket ct=new CheckTicket(target); TakingTrain proxy=(TakingTrain) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), ct); proxy.takeTrain("zhangsan"); } }
打印结果
please show your tickes Hi zhangsan Welcome to take the train
JDK中具体的动态代理类是怎么产生
- 产生代理类$Proxy0类 执行了Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 将产生$Proxy0类,它继承Proxy对象,并根据第二个参数,实现了被代理类的所有接口,自然就可以生成接口要实现的所有方法了(这时候会重写hashcode,toString和equals三个方法),但是还没有具体的实现体;
- 将代理类$Proxy0类加载到JVM中 这时候是根据Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)它的第一个参数----就是被代理类的类加载器,把当前的代理类加载到JVM中
- 创建代理类$Proxy0类的对象 调用的$Proxy0类的$Proxy0(InvocationHandler)构造函数,生成$Proxy0类的对象 参数就是Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)它的第三个参数 这个参数就是我们自己实现的InvocationHandler对象,我们知道InvocationHandler对象中组合加入了代理类代理的接口类的实现类;所以,$Proxy0对象调用所有要实现的接口的方法,都会调用InvocationHandler对象的invoke()方法实现;
- 生成代理类的class byte动态代理生成的都是二进制class字节
CgLib实现
好了,我们知道JDK的动态代理只能对接口进行代理,如果没有接口怎么办呢? CgLib可以为一个类创建一个子类,在子类中采用方法拦截的技术拦截父类所有方法的调用,你可以在这里加入你的横切逻辑。 还是上面的例子,下面我们用Cglib来实现:
public class CglibProxy implements MethodInterceptor{ private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable { System.out.println("please show your tickes"); return proxy.invokeSuper(arg0, arg2); } }
然后我们用这个CglibProxy代理类来获取TakingTrainImpl这个业务的实现类:
CglibProxy cglibProxy = new CglibProxy(); TakingTrainImpl takingTrain = (TakingTrainImpl) cglibProxy.getProxy(TakingTrainImpl.class); takingTrain.takeTrain("zhangsan");
上面的方法,我们直接使用了TakingTrainImpl,没有在使用它的接口,这就是JDK动态代理和CgLib的区别。
相关文章推荐
- Spring之JDK动态代理和cgLib的区别
- java动态代理(JDK和cglib)
- JAVA动态代理(JDK版本)
- cglib和jdk动态代理区别
- AOP的底层实现-CGLIB动态代理和JDK动态代理
- jdk动态代理和cglib动态代理小记
- JDK动态代理详解
- jdk动态代理的初步理解
- JDK解构 - Java中的引用和动态代理的实现
- jdk动态代理实现
- 菜鸟详解JDK动态代理之美
- 设计模式之动态代理 jdk实现
- Java动态代理模式jdk和cglib的2种实现以及二者的区别(AOP面向切面的前奏)
- Aop手动代理(jdk动态代理和CGLIB代理的区别)
- Spring -- tx:annotation-driven 注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别
- java动态代理(JDK和cglib)
- JDK动态代理实现拦截器
- java动态代理(JDK和cglib)
- jdk动态代理的实现原理
- java动态代理模式(jdk和cglib)