`

Spring-AOP底层原理-JDK动态代理---转载

 
阅读更多

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

 2 
 3 public class ForumServiceImpl implements ForumService {
 4 
 5  public void removeTopic(int topicId) {
 6          ①
 7   System.out.println("模拟删除Topic记录:"+topicId);
 8   try {
 9    Thread.currentThread().sleep(20);
10   } catch (Exception e) {
11    throw new RuntimeException(e);
12   }
13    ②
14  }
15  public void removeForum(int forumId) {
16          ①
17   System.out.println("模拟删除Forum记录:"+forumId);
18   try {
19    Thread.currentThread().sleep(40);
20   } catch (Exception e) {
21    throw new RuntimeException(e);
22   }
23          ②
24  }
25 }
    在代码清单 5中的①和②处,原来的性能监视代码被移除了,我们只保留了真正的业务逻辑。
    从业务类中移除的横切代码当然还得找到一个寄居之所,InvocationHandler就是横切代码的家园乐土,我们将性能监视的代码安置在PerformaceHandler中,如代码清单 6所示:
代码清单 6 PerformaceHandler
 1 package com.baobaotao.proxy;
    
 2 import java.lang.reflect.InvocationHandler;
 3 import java.lang.reflect.Method;
 4 
 5 public class PerformaceHandler implements InvocationHandler {
 6     private Object target;
 7  public PerformaceHandler(Object target){//①target为目标的业务类
 8   this.target = target;
 9  }
10  public Object invoke(Object proxy, Method method, Object[] args)
11    throws Throwable {
12   PerformanceMonitor.begin(target.getClass().getName()+"."+ method.getName());
13   Object bj = method.invoke(target, args);//②通过反射方法调用目标业务类的业务方法
14   PerformanceMonitor.end();
15   return obj;
16  }
17 }
    
 粗体部分的代码为性能监视的横切代码,我们发现,横切代码只出现一次,而不是原来那样星洒各处。大家注意②处的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:创建代理实例
 1 package com.baobaotao.proxy;
    
 2 import java.lang.reflect.Proxy;
 3 public class TestForumService {
 4  public static void main(String[] args) {
 5   ForumService target = new ForumServiceImpl();//①目标业务类
 6 //② 将目标业务类和横切代码编织到一起
 7   PerformaceHandler handler = new PerformaceHandler(target);
 8          //③为编织了目标业务类逻辑和性能监视横切逻辑的handler创建代理类
 9   ForumService proxy = (ForumService) Proxy.newProxyInstance(
10 target.getClass().getClassLoader(),
11     target.getClass().getInterfaces(),
12  handler);
13          //④ 操作代理实例
14   proxy.removeForum(10);
15   proxy.removeTopic(1012);
16  }
17 }
     
上面的代码完成了业务类代码和横切代码编织和接口代理实例生成的工作,其中在②处,我们将ForumService实例编织为一个包含性能监视逻辑的PerformaceHandler实例,然后在③处,通过Proxy的静态方法newProxyInstance()为融合了业务类逻辑和性能监视逻辑的handler创建一个ForumService接口的代理实例,该方法的第一个入参为类加载器,第二个入参为创建的代理实例所要实现的一组接口,第三个参数是整合了业务逻辑和横切逻辑的编织器对象。
按照③处的设置方式,这个代理实例就实现了目标业务类的所有接口,也即ForumServiceImpl的ForumService接口。这样,我们就可以按照调用ForumService接口的实例相同的方式调用代理实例,如④所示。运行以上的代码,输出以下的信息:
    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 动态...

    Spring-AOP(前置/后置/环绕)通知的例子

    Spring AOP通过动态代理机制(JDK Proxy或CGLIB)创建代理对象,拦截方法调用并执行通知。对于非接口实现类,Spring会使用CGLIB库生成子类;对于接口实现类,Spring会使用Java的动态代理。开发过程中,我们可以借助...

    spring-aop.rar_aop1270_spring_spring aop

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

    Spring AOP的底层实现技术

    Spring AOP基于两种代理机制实现:JDK动态代理和CGLIB代理。JDK动态代理适用于实现了接口的目标对象,通过反射机制创建一个代理类来拦截方法调用。而CGLIB是在运行时动态生成一个目标类的子类,从而实现对方法的...

    springIOC及AOP底层原理Demo实现

    基于代理的AOP主要使用JDK动态代理或CGLIB库生成目标对象的代理对象,代理对象在方法调用时拦截并执行通知。而基于字节码的AOP则在运行时修改目标类的字节码,将通知织入到方法的入口和出口。 为了实现自己的IoC和...

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

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

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

    同时,了解XML配置方式可以帮助我们理解Spring AOP的底层原理。 在实际开发中,理解并掌握这四种AOP实现方式对于编写高效、灵活的代码至关重要。Spring的AOP特性使得我们能够更好地组织代码,将横切关注点与业务...

    以注解方式模拟Spring IoC AOP

    - **基于代理的AOP**:Spring使用JDK动态代理或CGLIB动态代理创建目标对象的代理,代理对象在调用目标方法前后执行切面逻辑。 - **基于注解的AOP**:Spring支持在方法上直接定义切面注解,如`@Before`, `@After`, `...

    Spring2.0.8源码包

    在2.0.8版本中,Spring AOP主要通过代理模式实现,包括JDK动态代理和CGLIB代理,这两种代理方式在源码中都有详细的实现。 `spring-web`和`spring-webmvc`模块是针对Web应用的,前者提供了HTTP请求的处理,如Servlet...

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

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

    Spring aop 基于schema的AOP支持及JoinPoint的使用、如何使用CGLIB代理

    **Spring AOP 基于Schema的...CGLIB作为Spring AOP的底层代理技术,为我们提供了对未实现接口类的代理能力,使得AOP的应用场景更加广泛。理解并熟练掌握这些概念和技术,对于构建可维护、高性能的Spring应用至关重要。

    Spring-Reference_zh_CN(Spring中文参考手册)

    6.1.3. Spring的AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点(pointcut) 6.2.3.1. 切入点指定者的支持 6.2.3.2. 合并切入点表达式 6.2.3.3. 共享常见的切入点...

    spring1.2.6源码

    6. **AOP实现**:Spring使用JDK动态代理或CGLIB实现AOP代理,这在`org.springframework.aop.framework`包下可以找到。了解这两者的实现机制,有助于理解Spring如何在运行时创建和增强目标对象。 7. **事件驱动**:...

    动态代理,JDK实现动态代理,springAOP初学理解动态代理。代码实现

    在Spring AOP中,当目标对象实现了接口时,Spring默认使用JDK动态代理;如果没有实现接口,则使用CGLIB。通过动态代理,Spring可以在方法调用前后添加额外的行为,如切面(Aspect)中的前置通知(Before Advice)、...

    spring第五天 .pdf

    本课程主要关注Spring AOP的底层原理和源码分析,特别是动态代理机制。 动态代理是Spring AOP实现的核心,它允许在运行时创建一个代理对象,该对象能代理目标对象并执行额外的逻辑。在Java中,有两种主要的动态代理...

    spring03-5

    CGLIB代理在Spring AOP(面向切面编程)中扮演着重要角色,尤其是在处理没有实现接口的类时,因为Java的JDK动态代理只支持基于接口的代理。 CGLIB库是基于ASM库的,ASM是一个底层的Java字节码操纵和分析框架,可以...

    SpringAOP原理及拦截器.docx

    7. **AOP代理(AOP Proxy)**:Spring创建的包含通知的对象,可能是JDK动态代理或CGLIB代理。 8. **编织(Weaving)**:编织是指将方面与目标对象组合,创建被通知对象的过程,可以在编译时或运行时完成。Spring在运行...

    输出JDK和CGLib动态代理产生的class文件.zip

    本压缩包文件提供了两个示例项目,分别展示了JDK动态代理和CGLib动态代理的实现,帮助我们理解这两种技术的工作原理以及它们生成的class文件结构。 首先,我们来详细了解JDK动态代理。JDK动态代理基于Java的接口...

    【Spring】总结Spring整合Mybatis的底层原理实现步骤

    本文主要探讨Spring整合Mybatis的底层原理和实现步骤,结合鲁班学院公开课笔记,深入理解这一过程。 首先,Dao层是数据访问层,它提供了Service层调用的接口,有时甚至可以作为一个独立的项目。在Spring整合Mybatis...

    动态代理原理详细指南

    本篇文章将深入探讨代理模式的原理,特别是静态代理、JDK动态代理以及CGLIB动态代理。 1. **代理模式概述** 代理模式是设计模式中的结构型模式之一,它提供了一种方式来控制对目标对象的访问。代理对象可以看作是...

Global site tag (gtag.js) - Google Analytics