`

Spring AOP的底层实现技术---JDK动态代理

阅读更多

JDK动态代理
   
在JDK 1.3以后提供了动态代理的技术,允许开发者在运行期创建接口的代理实例。在Sun刚推出动态代理时,还很难想象它有多大的实际用途,现在我们终于发现动态代理是实现AOP的绝好底层技术。
    JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,在并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编织在一起。
   而Proxy为InvocationHandler实现类动态创建一个符合某一接口的代理实例。这样讲一定很抽象,我们马上着手动用Proxy和InvocationHandler这两个魔法戒对上一节中的性能监视代码进行AOP式的改造。
    首先,我们从业务类ForumServiceImpl 中删除性能监视的横切代码,使ForumServiceImpl只负责具体的业务逻辑,如所示:
代码清单 5 ForumServiceImpl:移除性能监视横切代码

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->package com.baobaotao.proxy; public class ForumServiceImpl implements ForumService { public void removeTopic(int topicId) { System.out.println("模拟删除Topic记录:"+topicId); try { Thread.currentThread().sleep(20); } catch (Exception e) { throw new RuntimeException(e); } } public void removeForum(int forumId) { System.out.println("模拟删除Forum记录:"+forumId); try { Thread.currentThread().sleep(40); } catch (Exception e) { throw new RuntimeException(e); } } }

    在代码清单 5中的①和②处,原来的性能监视代码被移除了,我们只保留了真正的业务逻辑。
    从业务类中移除的横切代码当然还得找到一个寄居之所,InvocationHandler就是横切代码的家园乐土,我们将性能监视的代码安置在PerformaceHandler中,如代码清单 6所示:
代码清单 6 PerformaceHandler

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->package com.baobaotao.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class PerformaceHandler implements InvocationHandler { private Object target; public PerformaceHandler(Object target){//①target为目标的业务类 this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { PerformanceMonitor.begin(target.getClass().getName()+"."+ method.getName()); Object bj = method.invoke(target, args);//②通过反射方法调用目标业务类的业务方法 PerformanceMonitor.end(); return obj; } }

    粗体部分的代码为性能监视的横切代码,我们发现,横切代码只出现一次,而不是原来那样星洒各处。大家注意②处的method.invoke(),该语句通过反射的机制调用目标对象的方法,这样InvocationHandler的invoke(Object proxy, Method method, Object[] args)方法就将横切代码和目标业务类代码编织到一起了,所以我们可以将InvocationHandler看成是业务逻辑和横切逻辑的编织器。下面,我们对这段代码做进一步的说明。
首先,我们实现InvocationHandler接口,该接口定义了一个 invoke(Object proxy, Method method, Object[] args)的方法,proxy是代理实例,一般不会用到;method是代理实例上的方法,通过它可以发起对目标类的反射调用;args是通过代理类传入的方法参数,在反射调用时使用。
    此外,我们在构造函数里通过target传入真实的目标对象,如①处所示,在接口方法invoke(Object proxy, Method method, Object[] args)里,将目标类实例传给method.invoke()方法,通过反射调用目标类方法,如②所示。
    下面,我们通过Proxy结合PerformaceHandler创建ForumService接口的代理实例,如代码清单 7所示:
代码清单 7 TestForumService:创建代理实例

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->package com.baobaotao.proxy; import java.lang.reflect.Proxy; public class TestForumService { public static void main(String[] args) { ForumService target = new ForumServiceImpl();//①目标业务类 //② 将目标业务类和横切代码编织到一起 PerformaceHandler handler = new PerformaceHandler(target); //③为编织了目标业务类逻辑和性能监视横切逻辑的handler创建代理类 ForumService proxy = (ForumService) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler); //④ 操作代理实例 proxy.removeForum(10); proxy.removeTopic(1012); } }

    上面的代码完成了业务类代码和横切代码编织和接口代理实例生成的工作,其中在②处,我们将ForumService实例编织为一个包含性能监视逻辑的PerformaceHandler实例,然后在③处,通过Proxy的静态方法newProxyInstance()为融合了业务类逻辑和性能监视逻辑的handler创建一个ForumService接口的代理实例,该方法的第一个入参为类加载器,第二个入参为创建的代理实例所要实现的一组接口,第三个参数是整合了业务逻辑和横切逻辑的编织器对象。
按照③处的设置方式,这个代理实例就实现了目标业务类的所有接口,也即ForumServiceImpl的ForumService接口。这样,我们就可以按照调用ForumService接口的实例相同的方式调用代理实例,如④所示。运行以上的代码,输出以下的信息:

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->begin monitor... 模拟删除Forum记录:10 end monitor... com.baobaotao.proxy.ForumServiceImpl.removeForum花费47毫秒。 begin monitor... 模拟删除Topic记录:1012 end monitor... com.baobaotao.proxy.ForumServiceImpl.removeTopic花费26毫秒。

   我们发现,程序的运行效果和直接在业务类中编写性能监视逻辑的效果一致,但是在这里,原来分散的横切逻辑代码已经被我们抽取到PerformaceHandler中。当其它业务类(如UserService、SystemService等)的业务方法也需要使用性能监视时,我们只要按照以上的方式,分别为它们创建代理对象就可以了。下面,我们用时序图描述调用关系,进一步代理实例的本质,如图1所示:
 
                                图 1代理实例的时序图
    我们在上图中特别使用虚线阴影的方式对通过代理器创建的ForumService实例进行凸显,该实例内部利用PerformaceHandler整合横切逻辑和业务逻辑。调用者调用代理对象的的removeForum()和removeTopic()方法时,上图的内部调用时序清晰地告诉了我们实际上所发生的一切。

分享到:
评论

相关推荐

    Spring Aop的底层实现技术 --- Jdk动态代理原理

    Spring AOP 的底层实现技术 --- Jdk 动态代理原理 JDK 动态代理是 Spring AOP 的底层实现技术,允许开发者在运行期创建接口的代理实例。在 JDK 1.3 以后,JDK 动态代理技术提供了实现 AOP 的绝好底层技术。JDK 动态...

    AOP之JDK动态代理和CGLib动态代理

    Spring框架是AOP实现的一个典范,它提供了两种主要的动态代理方式:JDK动态代理和CGLib动态代理。 **JDK动态代理**: JDK动态代理基于Java的反射API实现,适用于接口代理。当目标对象实现了至少一个接口时,Spring...

    Spring AOP的底层实现技术

    下面我们将深入探讨Spring AOP的底层实现技术和相关知识点。 1. **代理模式** Spring AOP基于两种代理机制实现:JDK动态代理和CGLIB代理。JDK动态代理适用于实现了接口的目标对象,通过反射机制创建一个代理类来...

    spring-cglib-repack-3.2.5.jar,spring-objenesis-repack-2.6.jar

    在Spring中,动态代理是实现AOP(面向切面编程)的核心技术之一。CGLIB和Java的内置JDK动态代理是两种常用的动态代理方式。当目标类实现了接口时,Spring会选择JDK动态代理,通过反射机制创建代理对象;反之,如果...

    spring jdk动态代理

    本文将深入探讨Spring如何利用JDK动态代理技术来实现这一功能,并通过实例解析其底层实现。 首先,让我们理解什么是JDK动态代理。在Java中,动态代理是一种在运行时创建代理类的能力,它允许我们为一组接口创建代理...

    spring 4.* 缺少jar spring-cglib-repack-3.2.5.jar_spring-objenesis-repack-2.6.jar

    在Spring框架中,CGLIB被用来创建AOP代理,尤其是当目标对象不支持JDK动态代理时(即目标对象没有实现接口)。CGLIB通过生成目标类的子类并覆盖其中的方法来实现动态代理,这样可以对方法进行拦截,实现如事务管理、...

    SpringAOP的实现机制(底层原理)、应用场景等详解,模拟过程的实例

    我们还提供了实际示例,演示如何在Spring AOP中使用JDK动态代理。 CGLib动态代理: 我们将深入研究CGLib动态代理,它允许您在不需要接口的情况下创建代理对象。您将了解CGLib的工作原理,以及如何生成子类来实现...

    个人用java动态代理模拟实现spring aop

    Java动态代理是Java提供的一种在运行时创建新类型对象的技术,它可以让我们在不修改原有代码的情况下,对方法的调用进行增强,这正是Spring AOP(面向切面编程)的核心思想。Spring AOP通过代理模式实现了对业务逻辑...

    Spring实现AOP的4种方式 - Java -

    Spring默认使用JDK的动态代理机制实现AOP。当目标对象实现了至少一个接口时,Spring会创建该接口的代理对象。在代理对象上调用方法时,会触发切点匹配并执行相应的通知。动态代理的实现依赖于Java的`java.lang....

    开源框架spring详解-----AOP的深刻理解

    标签中的“源码”提示,这篇博文中可能还涉及到了Spring AOP的底层实现,可能分析了Spring如何通过代理模式生成拦截器链,以及如何在运行时解析并执行切点表达式。了解这些底层机制有助于开发者更有效地利用AOP,...

    spring-aop底层1

    【Spring-AOP底层详解】 Spring AOP,即Spring的面向切面编程,是Spring框架中的一个重要组成部分,它提供了一种在运行时动态插入代码的能力,主要用于处理横切关注点,如日志记录、事务管理、权限校验等,从而降低...

    Spring AOP IOC源码笔记.pdf

    Spring AOP基于代理实现,可以使用接口代理(JDK动态代理)或类代理(CGLIB)。 7. CGLIB: CGLIB是Spring AOP默认的代理库,用于生成目标类的子类,从而实现方法拦截。当目标类没有实现接口时,Spring会使用CGLIB...

    AOP-CGLIB学习-实现简单的注解权限系统

    Spring框架提供了一种实现AOP的方式,它支持基于代理的AOP实现,包括JDK动态代理和CGLIB代理。当目标对象不实现接口时,Spring会使用CGLIB来创建代理对象。 CGLIB(Code Generation Library)是一个代码生成库,它...

    spring-aop.rar_aop1270_spring_spring aop

    Spring AOP通过动态代理来实现,主要有两种代理方式: 1. JDK动态代理:适用于实现了接口的目标对象,通过反射创建代理对象,代理对象在调用真实对象方法前/后执行通知。 2. CGLIB代理:如果目标对象没有实现接口...

    day3-springAOP.md

    AOP 的底层实现主要依赖于动态代理技术。Spring 框架提供了两种主要的动态代理技术: - **JDK 动态代理**:适用于实现接口的情况。它利用 Java 的反射机制,在运行时动态地生成代理对象。 - **CGLIB 动态代理**:...

    jdk与cglib动态代理与底层实现

    JDK和CGLIB是Java中实现动态代理的两种主要方式,它们在Spring框架中扮演着关键角色,尤其是在AOP(面向切面编程)中。 1. **JDK动态代理**: JDK动态代理基于Java的接口机制实现,因此,要使用JDK动态代理,被...

    Spring中aop编程所需要的jar包

    它实现了基于代理的AOP模型,可以创建JDK动态代理或CGLIB代理。 3. **Spring Aspects包**: - `spring-aspects.jar`: 这个包扩展了Spring AOP的功能,支持与AspectJ集成。AspectJ是一个全面的AOP框架,提供了编译...

    java中动态代理,springAop.pdf

    Spring AOP(面向切面编程)是Spring框架的一部分,它利用了动态代理来实现切面的功能,如日志、事务管理、性能监控等。现在,让我们深入探讨Java动态代理及其在Spring AOP中的应用。 首先,我们需要了解Java动态...

Global site tag (gtag.js) - Google Analytics