AOP原理及在架构设计中的应用(一)

系统 1723 0

AOP 原理及应用

 

【摘要】 面向方面的编程(AOP)技术已在Java领域产生多年,它为传统的编程模式带来了一种新的思维和方式。AOP本身为程序结构带来的灵活性,在JavaEE架构设计上也能发挥极大的作用。本文对AOP原理,Spring AOP基本编码方式进行了简明,清晰的介绍,还对公司项目实践中AOP的基本应用模式进行了归纳,整理, 有更贴近实践的指导意义。

 

【关键词】AOP  JavaEE 架构设计

 

1.        AOP 原理

1.1.     AOP 是什么

    AOP(Aspect-Oriented Programming) 就是面向方面的编程,这一概念最初由 Xerox PARC 研究中心提出。

     AOP 技术使得应用开发者仅仅关注于业务逻辑本身的开发,而不用纠缠于那些诸如安全、事务、日志等和业务逻辑无关但又是系统有效地执行业务逻辑所必须的通用性功能。 AOP 以“动态织入”的方式大大提高应用开发效率,有效地降低软件的复杂性,代码的清晰性、模块化、可测试性方面也会取得很好的提升。

 

1.2.     AOP 产品

     经过多年的发展,目前 Java 领域的 AOP 实现有多种方案,主要包括:

     1 AspectJ  (TM) : 创建于 Xerox PARC.  有近十年历史,技术成熟。但其过于复杂;破坏封装;而且需要专门的 Java 编译器,易用性较差。

     2 )动态代理 AOP :使用 JDK 提供的动态代理 API 或字节码 Bytecode 处理技术来实现。

     基于动态代理 API 的具体项目有:   JBoss  4.0  JBoss  4.0 服务器
     3
)基于字节码的 AOP ,例如:  
Aspectwerkz ,  CGlib Spring 等。

      

1.3.     AOP 原理

1.3.1. 基本概念

AOP 技术中将这些通用性功能称为方面( Aspect )或切面( Pointcut , Advicor )。    JDK 提供的动态代理 AOP CGLib 等字节码的 AOP 中,方面通过拦截器 (Interceptor) 来实现。

     具体解释就是,在对 Java 方法调用时, AOP 机制能自动进行方法拦截,允许你在方法调用前,调用后,以及执行异常时添加特定的代码,来完成需要的功能。

     例如:调用 User 类的 sayHello 方法的基本过程如下图:

 

public   class  User   {

public   void   sayHello (String name)  {    

System.out.println ( "Hello " + name); 

}

}

    如果想在调用前打印一条日志, AOP 下的做法是为 User 类添加一个日志拦截器(如下图所示),而原有 User 类的代码无需任何修改。

 

      

1.3.2. 方法拦截器

    不同厂商提供的方法拦截器规格不同,但基本原理类似。 CGLib 提供的拦截器接口: MethodInterceptor ,仅提供了一个 intercept 接口( AOPAppliance 提供类似的 invoke 方法)。

 

public Object intercept

(Object obj , Method method , Object[] args , MethodProxy proxy) throws Throwable

    日志拦截器的开发者,可以实现该接口,对被拦截的方法,例如: sayHello 进行处理,在方法实际执行前,打印日志。

 

public class LogInterceptor implements MethodInterceptor {   

public Object intercept(Object obj , Method method , Object[] args , MethodProxy proxy) throws Throwable {     

        System. out .println ( "invoke method(Before) sayHello !" );

        // 实际执行方法

        return proxy.invokeSuper ( obj , args );

    }

}

 

    原方式下, user 的调用方式为

     User user = new User( );

     user.sayHello ( “张三” );

 

     但要让 User sayHello 方法被记录日志, user 的创建方式有所不同。在 Spring 下,提供了一种最为简化的创建方法,

     User user = (User) beanFactory.getBean ( beanName )

     user.sayHello ( “张三” );

    其中 beanName 是在 Spring 配置文件中为 User 配置的 bean ID

 

1.3.3. 细化的拦截器

    Spring 框架对 AOP 的方面进行了细化处理,将每一次的方法拦截细分为 before after throwing( 异常 ) 三个过程,并定义了三个 advice 接口

MethodBeforeAdvice ,

AfterReturningAdvice ,

ThrowsAdvice ,

     拦截器开发者只需实现自己关注的阶段,上面的日志拦截器在 Spring 框架下可以如下实现:

 

public class LogAdvisor extends MethodBeforeAdvice {

private static Log log = LogFactory.getLog ( LogAdvisor.class );

public void before(Method method , Object[] args , Object target) throws Throwable {

        if( log.isDebugEnabled ())

            log.debug (" 记录日志 ( ):" + target +", 方法 :" + method.getName ());

}

 

      

1.3.4. 拦截器串

       通常,系统关注的功能有很多,例如:日志,事务,缓存等等,因此,实际系统中,通常是多个拦截器同时工作,形成一个拦截器串,各自关注相应特定的功能

 

         拦截器串协同 工作的基本方式为

     1 )串行执行,即几个拦截器,按顺序依次执行。

     但在有些系统中还存在特殊需求:

     2) 忽略执行

     在某些情况下,例如: sayHello 的参数是“ Admin ”时,不记录日志,只开启事务和缓存功能, 那么 Log 拦截器的日志记录功能需要被忽略。这种情况通常在 LogAdvisor 内部,对参数进行判断来实现。

public class LogAdvisor extends MethodBeforeAdvice {

private static Log log = LogFactory. getLog ( LogAdvisor. class );

public void before(Method method , Object[] args , Object target) throws Throwable {

        if( Admin .equals ( args [0]))

            if ( log .isDebugEnabled ())

                log .debug ( " 记录日志 ( ):" + target + ", 方法 :" + method.getName ());

}

    3) 跳出执行

       在某些情况下,要求终止被拦截的方法的实际执行,不再继续执行下一拦截器,而直接返回特定的结果,例如: sayHello 的参数是“ Admin ”时,让该方法返回固定的值“管理员,你好!”。

 

public class SecurityInterceptor implements MethodInterceptor {  

public Object intercept(Object obj , Method method , Object[] args , MethodProxy proxy) throws Throwable {     

        if ( Admin .equals ( args [0]))

            return 管理员,你好! ; // 实际执行方法

        else

            return proxy.invokeSuper ( obj , args );

    }

}

 

 

 

1.3.5. AOP 适用的方面

       由于 AOP 技术本身的插件式特点,采用这种机制进行系统设计和程序开发能够为软件带来极大的灵活性和扩展性。目前,运用 AOP 对系统进行功能扩展主要关注的方面是:

     Transactions 事务,例如 Spring 就利用 AOP 提供了通用性的事务管理器。

     Logging, 日志,还包括 Tracing 等;

     Profiling and Monitoring 性能分析和监控。

     Authentication 权限,包括鉴权,安全控制等;

     Caching 缓存,     

     Error handling 错误处理

     Lazy loading 懒加载

     Debugging   调试    

     Performance optimization 性能优化

     等等。

      

2.        架构设计中 AOP 的运用

2.1.     运用方式

    架构采用了 JavaEE 规范中经典的三层架构:表示层、业务层、持久层,如下图所示:

 

   

      与一般的 JavaEE 架构不同, 该架构通过 Factory 模式在各层之前进行搭桥,通过对应的 Factory 类来创建下层对象。

     工厂机制运用了 Spring AOP 技术,上层对象在请求下层资源时,可以通过代理机制切入若干功能,使得可以灵活扩展系统功能,而又使各层着重关注本职核心功能。值得注意的是,表示层采用的是 Struts2 框架,而它本身就是基于 AOP 原理进行设计的。如下图所示:

      

     由于运用了 Spring AOP 技术,方面( Aspect )的开发就变成拦截器( Spring 称为 Advisor )的开发。该架构将 Spring AOP 规范定义的 before after throwing 三个阶段,和 CGLib 定义的 invoke 阶段整合为了一个抽象类 : AbstractAdvisor , 方便设计人员开发新的拦截器。

   

    并且 Spring 通过 AOP 机制已经提供通用的事务( Transaction )控制,调试 (Debug) ,类加载分析,并发控制,简单的性能监控等基础性功能。

2.2.     AOP 应用举例

2.2.1. 基本功能

1.        业务日志(工单)

       凡是基于数据库的系统,本质上都是对 库表记录 的增删改查。而从业务层面看,很多时候,用户需要对数据的操作留下痕迹,即业务日志,以便审计。

         在公司项目的 J2EE 架构中设计了业务日志拦截器,并切入对 BO 的操作,完成对业务操作的记录。用户可以通过专门的界面对业务日志进行查询和分析。

         工作原理

         业务日志的基本数据格式为:

           操作时间 , 来源 IP, 操作工号 , 操作状态 , 操作动作 , 操作类型 , 失败原因 , 数据

         日志按操作类型分:增加,删除,修改(查询暂不记录), 操作成功,失败时都要记录。记录业务日志的主要依据是被拦截的对象和方法信息,。在执行方法本体后,即业务方法成功执行后,记录成功日志;在方法本体抛出异常时,记录失败日志。主要代码见下:

 

public class BusinessLogAdvisor extends AbstractAdvisor   {

 

public Object invoke( MethodInvocation invocation) throws Throwable {

     // 准备参数

     Object result = null ;     

     Object object = invocation.getThis (); // 被拦截的对象

     Method method = invocation.getMethod (); // 被拦截的方法

     Object[] args = invocation.getArguments (); // 参数

     //before, 之前必要的检查

     ……

     try {

         result = invocation.proceed ();

         // 以下执行记录日志的操作

         doLog ( object, method, args , target, BusinessLog. STATE_SUCCESS , null );

     } catch (Exception e) {

         // 以下记录失败日志

         doLog ( object, method, args , target , BusinessLog. STATE_FAIL ,failcause );

     }

}

         其中 doLog 方法将信息保存到库表中。 ( 出于性能考虑,可以采用异步方式保存业务日志到数据库 )

 

2.        性能监控

       Spring 本身提供了一个监控拦截器,但功能不是很完善。公司项目架构中设计了一套 Monitor 框架,其功能包含:性能监控 (Profiling , Monitoring) ,访问分析 (Analyzing) 两个方面。

         Monitor 可切入表示层,业务层 BO ,持久层 DAO 三层。 Monitor 包括以下功能:

¨           按安模块和功能分析性能指标

¨           实时流量监控

¨           按模块和功能分析流量

¨

AOP原理及在架构设计中的应用(一)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论