Java学习之:JDK动态代理与CGLIB动态代理

代理的概念:简单的理解就是通过为某一个对象创建一个代理对象,我们不直接引用原本的对象,而是由创建的代理对象来控制对原对象的引用。

动态代理:是指在程序运行时由Java反射机制动态生成,无需手动编写代码。动态代理不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理类。

代理原理:代理对象内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

以下通过一个简单的例子来看基于JDK动态代理与CGLIB分别如何实现代理。

代理接口UserService:

1 package com.liang.test;
2
3 public interface UserService {
4     public void say(String arg);
5 }

UserService实现类UserServiceImpl:

1 package com.liang.test;
2
3 public class UserServiceImpl implements UserService {
4     @Override
5     public void say(String arg) {
6         System.out.println("hello, I am " + arg);
7     }
8 }

JDK通过java.lang.reflect包下的Proxy类和一个InvocationHandler接口来生成动态代理类和动态代理对象。

首先创建一个实现InvocationHandler接口的调用控制器对象MyInvocationHandler:(当执行动态代理对象里的目标方法时,实际上会替换成调用MyInvocationHandler的invoke方法)

 1 package com.liang.test;
 2
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5
 6 public class MyInvocationHandler implements InvocationHandler { //实现InvocationHandler
 7
 8     private Object object; //被代理对象
 9
10     public MyInvocationHandler(Object object){ //接收被代理对象
11         this.object = object;
12     }
13     @Override
14     public Object invoke(Object proxy, Method method, Object[] args)
15             throws Throwable { //say()方法被替换执行成当前方法,可在其中添加额外功能增强目标方法
16         System.out.println("before method");
17         Object obj = method.invoke(object, args); //通过反射调用UserService的say()方法
18         System.out.println("after method");
19         return obj;
20     }
21
22 }

通过Proxy结合MyInvocationHandler为UserService创建动态代理类:

 1 package com.liang.test;
 2
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Proxy;
 5
 6 public class TestProxy {
 7
 8     public static void main(String[] args) {
 9         UserService userService = new UserServiceImpl();
10         InvocationHandler handler = new MyInvocationHandler(userService);
11
12         UserService proxy = (UserService)Proxy.newProxyInstance(userService.getClass()
13                 .getClassLoader(), userService.getClass().getInterfaces(),
14                 handler);
15         proxy.say("孙悟空"); //调用代理实例
16     }
17
18 }

运行结果:

before method
hello, I am 孙悟空
after method

可以看到执行代理实例的say方法时执行的是MyInvocationHandler的invoke()方法。

而CGLIB则是采用非常底层的字节码技术,为被代理对象创建一个子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,并顺势植入增强代码。CGLIB实现动态代理的示例如下:

 1 package com.liang.test;
 2
 3 import java.lang.reflect.Method;
 4
 5 import net.sf.cglib.proxy.Enhancer;
 6 import net.sf.cglib.proxy.MethodInterceptor;
 7 import net.sf.cglib.proxy.MethodProxy;
 8
 9 public class CglibProxy implements MethodInterceptor {
10
11     private Enhancer enhancer = new Enhancer();
12
13     public Object getProxy(Class clazz) {
14         enhancer.setSuperclass(clazz); // 设置需要创建子类的类
15         enhancer.setCallback(this);
16         return enhancer.create();// 创建子类实例
17     }
18
19     @Override
20     public Object intercept(Object object, Method method, Object[] args,
21             MethodProxy proxy) throws Throwable { //拦截父类中所有的方法调用
22         System.out.println("cglib: before method");
23         Object obj = proxy.invokeSuper(object, args); //通过代理类调用父类中的方法
24         System.out.println("cglib: after method");
25         return obj;
26     }
27
28 }

测试代码:

 1 package com.liang.test;
 2
 3 public class TestProxy {
 4
 5     public static void main(String[] args) {
 6         CglibProxy proxy = new CglibProxy();
 7         UserServiceImpl userServiceImpl = (UserServiceImpl)proxy.getProxy(UserServiceImpl.class);
 8         userServiceImpl.say("孙悟空");
 9     }
10
11 }

运行结果:

cglib: before method
hello, I am 孙悟空
cglib: after method

小结:JDK动态代理与CGLIB动态代理最常见的应用是SpringAOP的底层实现,基于JDK的动态代理在创建代理对象时所花费的时间比CGLIB短,但是JDK只能为接口创建代理实例,这一点可以从newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)中看出:第二个入参就是代理示例实现的接口列表。而CGLIB创建的代理对象性能比JDK创建的代理对象高,但是花费的时间相对长一些,并且由于CGLIB采用动态创建子类的方式生成代理对象,所以对于由final修饰的方法不能通过CGLIB进行代理。基于此,我们对于singgleton的代理对象或者具有实例池的代理比较适合使用CGLIB动态代理技术,对于每次都要new出新实例的一般采用JDK的动态代理技术。

本次学习资料参照了:

  1.《精通Spring2.x-企业应用开发详解》——陈雄华著;

  2.http://rejoy.iteye.com/blog/1627405——JDK动态代理实现原理

        

时间: 2024-11-05 02:36:44

Java学习之:JDK动态代理与CGLIB动态代理的相关文章

Java进阶之 JDK动态代理与Cglib动态代理

一.动态代理概述: 与静态代理对照(关于静态代理的介绍 可以阅读上一篇:JAVA设计模式之 代理模式[Proxy Pattern]), 动态代理类的字节码是在程序运行时由Java反射机制动态生成. 注意: 1.AspectJ是采用编译时生成AOP代理类,具有更好的性能,但是需要使用特定的编译器进行处理 2.Spring AOP采用运行时生成AOP代理类,无需使用特定编译器进行处理,但是性能相对于AspectJ较差 二.JDK动态代理 [对有实现接口的对象做代理] 1.JDK动态代理中 需要了解的

Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)

一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法.如果公司卖多少钱,代理商也卖多少钱,那么代理商就赚不了钱.所以代理商在调用公司的卖方法后,加上自己的利润然后再把产品卖给客户.而客户部直接跟公司打交道,或者客户根本不知道公司的存在,然而客户最终却买到了产品. 专业点说:代理模式是对象的结构型模式,代码模式给某一个对象提供代理,并由代理对象控制原对象

JDK动态代理和CGLIB动态代理

转载自http://www.itzhai.com/java-dong-tai-dai-li-zhi-jdk-dong-tai-dai-li-he-cglib-dong-tai-dai-li-mian-xiang-qie-mian-bian-cheng-aop-yuan-li.html 静态代理 静态代理相对来说比较简单,无非就是聚合+多态: 参考:设计模式笔记 – Proxy 代理模式 (Design Pattern) 动态代理 我们知道,通过使用代理,可以在被代理的类的方法的前后添加一些处理方

代理模式 & Java原生动态代理技术 & CGLib动态代理技术

第一部分.代理模式  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务.(其实就是在代理类中关联一个委托类的实例,然后在代理类中进行包装). UML图如下: 第二部分.在Java中实现代理模式  按照代理的创建时期,代理类可以分

关于JDK动态代理和CGLIB动态代理

1. 代理模式 一句话总结:为其他对象提供一种代理以控制对这个对象的访问.千篇一律的介绍:代理模式是常用的java设计模式,他的特征是代理类与委托类(或目标类)有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工具

JDK动态代理与Cglib动态代理(转载)

spring容器通过动态代理再结合java反射思想可以使得方法调用更加简洁 一.动态代理概述: 与静态代理对照(关于静态代理的介绍 可以阅读上一篇:JAVA设计模式之 代理模式[Proxy Pattern](博主), 动态代理类的字节码是在程序运行时由Java反射机制动态生成. 注意:       1.AspectJ是采用编译时生成AOP代理类,具有更好的性能,但是需要使用特定的编译器进行处理 2.Spring AOP采用运行时生成AOP代理类,无需使用特定编译器进行处理,但是性能相对于Aspe

【Spring】AOP之JDK动态代理和CGLib动态代理

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 一.JAVA动态代理  1.1 代理模式         代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创

Spring 静态代理+JDK动态代理和CGLIB动态代理

代理分为两种:静态代理 动态代理 静态代理:本质上会在硬盘上创建一个真正的物理类 动态代理:本质上是在内存中构建出一个类. 如果多个类需要进行方法增强,静态代理则需要创建多个物理类,占用磁盘空间.而动态代理则是在内存中创建,不会对磁盘进行影响. 静态代理和JDK动态代理需要有接口. CGLIB动态代理无需有接口的情况下进行代理.实质:内存中构建出了目标类型的子类. JDK动态代理是JDK提供的,CGLIB动态代理是Spring提供的. 代理模式的三个组件:抽象主题 真实主题 代理主题 静态代理:

spring aop原理 JDK动态代理和CGLIB动态代理

Spring的两大特性是IOC和AOPIOC负责将对象动态的注入到容器,从而达到一种需要谁就注入谁,什么时候需要就什么时候注入的效果.理解spring的ioc也很重要.但是今天主要来和大家讲讲aop.AOP 广泛应用于处理一些具有横切性质的系统级服务,AOP 的出现是对 OOP 的良好补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理.日志.缓存等等. AOP实现的关键在于AOP框架自动创建的AOP代理.AOP代理主要分为静态代理和动态代理, 静态代理的代表为AspectJ:动态代理则