`

AOP分解

阅读更多

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

 

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

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:创建代理实例

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接口的实例相同的方式调用代理实 例,如④所示。运行以上的代码,输出以下的信息:

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()方法时,上图的内部调用时序清晰地告诉了我们实际上所 发生的一切。  

  • 大小: 5.5 KB
分享到:
评论

相关推荐

    Spring AOP教程

    Spring框架的关键组件之一是面向方面编程(AOP)框架。 面向方面的编程需要将程序逻辑分解成不同的部分。 此教程将通过简单实用的方法来学习Spring框架提供的AOP/面向方面编程。

    论文研究-Java动态代理在AOP中的应用 .pdf

    Java动态代理在AOP中的应用,薄栋,邓芳,AOP(Aspect-Oriented-programming)是一种支持横切关注点的分解的技术,表达更高的抽象层次。它对于横切关注点就像面向对象程序设计对于对象�

    SpringAOP介绍及源码分析

    如果说面向对象编程可以对业务需求进行很好的分解使之模块化;那么面向切面编程AOP(Aspect-OrientedProgramming)则可以对系统需求进行很好的模软件开发经历了从汇编语言到高级语言和从过程化编程到面向对象编程;...

    spring-aop:易百教程网-Spring AOP教程源代码(http

    SpringAOP 易百教程网-Spring AOP教程源代码( ) Spring框架的关键组件之一是面向方面编程(AOP)框架。面向方面的编程需要将程序逻辑分解成不同的部分。 此教程将通过简单实用的方法来学习Spring框架提供的AOP /...

    spring.net權限管理實例

    AOP 则把程序分解为一系列方面(aspects)或者关注点(concerns)。AOP将诸如事务管理等本来横向分布在多个对象中的关注点进行了模块化处理(这些关注点也常称为横切(crosscutting)关注点)。在Spring.NET中提供了...

    偏振图像分析工具。去马赛克、斯托克斯向量、穆勒矩阵_python_代码_下载

    偏振分析仪 Polanalyser 是偏振图像分析工具。

    aspectj-1.9.3.jar

    Spring 框架的一个关键组件是面向方面的编程(AOP)框架。面向方面的编程需要把程序逻辑分解成不同的部分称为所谓的关注点,spring的AOP面向切面所需jar包,网上资源较少,欢迎大家下载

    深入理解Spring声明式事务:源码分析与应用实践

    Spring通过@Transactional注解以及底层的AOP和代理机制实现了声明式事务。这个机制允许开发者通过简单的注解就能控制事务的边界和规则,极大地简化了编程模型。在Spring中,事务管理是通过一系列的拦截器和事务管理...

    论文研究 - UV-C / H2O2和Sunlight / H2O2是处理生活污水再利用中现有敢于使用的最佳技术的核心

    尽管在应用AOP并了解其去除ARB和ARG的机理方面已取得了巨大的进步,但仍可能产生现有抗生素的转化产物(TPs),这些产物的生物可分解性较低,毒性更大,生物强度更高,并列母体化合物。 因此,尝试必须集中在定义...

    Spring面试题

    使用 AOP 后,公共服务 (比如日志、持久性、事务等)就可以分解成方面并应用到域对象上,同时不会增加域对象的对象模型的复杂性。 IOC 允许创建一个可以构造对象的应用环境,然后向这些对象传递它们的协作对象。...

    seasar2中文文档

    S2Container定义的分解和引入 名称空间 实例管理 生存周期 自动绑定 组件中利用S2Container S2ContainerServlet app.dicon的角色 AOP的适用范围 META数据 Request的自动绑定 组件的自动登陆 Aspect的...

    世纪神码输入法(内有注册文件,支持最新windows7系统)

    对汉字编码,具体地说就是把汉字分解成字元,用字元的代码来拼写汉字的编码,如:“命”分解成‘亼口卩’,编码为‘AOP’、“居”分解成‘尸十口’,编码为‘PXO’。究竟哪些才是字元,以是否与英文字母象形为选用...

    软件系统设计方案.pdf

    其AOP特性,对重复模块进⾏集 中,实现事务,⽇志,权限的控制;SpringMVC是使⽤了MVC设计思想的轻量级web框架,对web层进⾏解耦,与Spring⽆缝衔接,有着灵 活的数据验证,格式化,数据绑定机制;Mybatis中数据库的...

    AutoPerfMonJS:使用面向方面的编程在JavaScript中进行自动(和不可见)性能测量

    它具有一系列本地功能,清楚地记录了设置AOP,执行一些慢代码,报告时序测量以及分解所应用的AOP的过程。 它使用两种截然不同的代码样式。 用于引入Meld库,因为它是使用该依赖模块格式构建的。 为了保持一致性,...

    SpringMVC全套JAR包

    SpringMVC全套JAR包 spring-aop 面向切面JAR, spring-ams ASM字节码库,spring-context,spring-core,spring-expression 基本表达式,类相关表达式,集合相关表达式,其他表达式(单词分解,词法分析 ,生成语法树 )

    几个小小的Java案例

    现阶段,EJB是复杂的,它不是为了复杂而复杂。... 简单地说,Spring是一个轻量级的IoC和AOP容器框架。也许这个描述并不简单,但它确实概括出了Spring的功能。为了深入了解Spring,让我们把这个描述分解开来。

    Spring.net框架

    在这个系列中一共包含6个案例,从简单到复杂,也是对问题分解、思考和解决的一个过程,它们分别是: (1)类之间的依赖; 降低 (2)接口依赖; (3)基 于配置文件和Reflection的工厂模式; (4)使用Spring.net...

    2015_07_08-module_prepend:Colin Kelley使用Ruby 2.1的Module#prepend进行面向方面的编程,2015年7月8日发表

    面向方面的编程(AOP)是一种通过方法调用上的装饰器来分隔横切关注点的技术。 装饰器的编码方式与它们增加的方法无关,因此可以重复使用和组合装饰器。 从一开始就使用#alias_method_chain在Ruby on Rails中几乎...

    EShop-SOA:EShop基于Dubbo实现SOA服务化分解,并基于RocketMQ解决了分布式事务(新版SpringBootSOASkeleton)

    SOA网上商店 介绍请参见 Dubbo + TCC分布式事务 业务细分 用户类别: 用户模块:用户+邮件,涉及用户,角色,邮件,邮件文本,余额表 产品模块:产品,涉及产品,类别表 新闻模块:新闻,涉及新闻表 ...

Global site tag (gtag.js) - Google Analytics