动态代理双剑客--JDK Proxy与CGLIB
2013-09-09 08:32
351 查看
背景:
研究过设计模式的同胞们都知道代理模式可以有两种实现方案:1.接口实现(或继承抽象类)
核心代码片段
ProxySubject-->>doOperation()
//dosomething before realSubject.doOperation() //dosomething after
2.继承父类
核心代码片段
ProxySubject-->>doOperation()
//dosomething before super.doOperation() //dosomething after
总结:
相同点都可以通过Proxy控制对Target的访问
不同点
可行性
如果Target实现了接口,那么这两种方式都可以;
如果没有实现任何接口,那只能采取“继承父类”的方式了
正文
Java中动态代理对应着也有两种实现方式1.“接口实现"---JDK Proxy
用到JDK提供的InvocationHandler接口和Proxy类类之间的关系如下
InvocationHandler接口
用于处理方法请求
Proxy类
用于生成代理对象
代码演示
ISubject接口
public interface ISubject { public void showName(String name); }
RealSubject类
public class RealSubject implements ISubject { @Override public void showName(String name) { System.out.println(name+"闪亮登场"); } }
LogHandler类
为了更明确的说明动态代理的工作原理,将代理的创建过程放到了LogHandler的外部,即main方法中
public class LogHandler implements InvocationHandler { Object target=null; public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result=null; //调用目标对象方法前的逻辑 System.out.println("下面有一个大人物要出现"); //调用目标对象的方法,这句代码将代理与目标类联系了起来 method.invoke(target, args); //调用目标对象方法后的逻辑 System.out.println("大家鼓掌欢迎"); return result; } }
客户端类Client
public class Client { /** * @param args */ public static void main(String[] args) { LogHandler logHandler=new LogHandler(); logHandler.setTarget(new RealSubject()); //创建代理对象 ISubject proxySubject=(ISubject)Proxy.newProxyInstance(RealSubject.class.getClassLoader(), RealSubject.class.getInterfaces(), logHandler); System.out.println("-------JDK Proxy-------------"); proxySubject.showName("委座"); } }
执行结果
调用过程时序图
2.“继承父类”---CGLIB
用到了CBLIB提供的Enhancer类和MethodInterceptor接口类之间的关系如下
需要引入第三方jar包
cglib-2.2.jar
asm-3.1.jar
Enhancer类
用于创建代理对象
MethodInterceptor接口
用于处理方法请求
代码演示
RealSubject类同上,但是个pojo类
public class RealSubject { public void showName(String name) { System.out.println(name+"闪亮登场"); } }
LogIntercept类
public class LogIntercept implements MethodInterceptor { Object target=null; public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { Object result=null; //调用目标对象方法前的逻辑 System.out.println("下面有一个大人物要出现"); //调用目标对象的方法,这句代码将代理与目标类联系了起来 arg3.invoke(target, arg2); //调用目标对象方法后的逻辑 System.out.println("大家鼓掌欢迎"); return result; } }
客户端类Client
public class Client { /** * @param args */ public static void main(String[] args) { LogIntercept logIntercept=new LogIntercept(); logIntercept.setTarget(new RealSubject()); Enhancer enhancer=new Enhancer(); enhancer.setSuperclass(RealSubject.class); enhancer.setCallback(logIntercept); <pre name="code" class="java"> RealSubject proxySubject=(RealSubject )enhancer.create(); System.out.println("-------CBLIB-------------"); proxySubject.showName("委座"); } }
调用过程时序图
总结
大家可以看到JDK Proxy和CGLIB这两种动态代理的实现过程是非常相似的,但也有区别相同点:
都用到了一个接口一个类;
接口用于处理方法调用,类用于创建代理对象
JDK Proxy
InvocationHandler接口
Proxy类
CGLIB
MethodIntercept接口
Enhancer类
不同点:
JDK Proxy
使用目标类的接口创建动态代理
CBLIB
使用目标类的子类创建动态代理
最后
JDK Proxy和CGLIB两种动态代理各有千秋,具体用哪个方案要看具体情况。如果目标类实现了对应接口,两种方案都可以;如果没有实现任何接口则要使用CBLIB。比如Hibernate中的实体类是POJO类,没有实现任何接口,那么要通过代理实现延迟加载就只能采用CGLIB方案了。相关文章推荐
- 动态代理双剑客--JDK Proxy与CGLIB
- Spring(十)通过动态代理(JDK的Proxy)和cglib实现AOP技术
- 动态代理-JDK_proxy&cglib
- 动态代理-JDK_proxy&cglib
- Cglib 与 JDK动态代理的运行性能比较
- 动态代理:JDK动态代理和CGLIB代理的区别
- java动态代理(JDK和cglib)
- java动态代理(JDK和cglib)
- 动态代理的两种方式jdk和cglib
- Java动态代理(JDK和cglib)
- java动态代理(JDK和cglib)
- java动态代理(JDK和cglib)
- Spring: proxy-target-class 决定 用 CGlib 还是 JDK AOP 来生成代理
- JDK动态代理与CGLIB动态代理
- JDK中的proxy动态代理原理剖析
- jdk动态代理和cglib代理demo及总结
- jdk的动态代理和CGLIB的区别
- JDK动态代理与CGLib动态代理
- java动态代理(JDK和cglib)
- java 动态代理 及jdk和cglib的区别