zoukankan      html  css  js  c++  java
  • 依赖注入及AOP简述(十二)——依赖注入对象的行为增强(AOP) .

    四、依赖注入对象的行为增强(AOP)

    前面讲到,依赖注入框架的最鲜明的特点就是能够提供受容器管理的依赖对象,并且可以对对象提供行为增强(AOP)功能,所以这一章我们来讨论有关AOP的话题。

    1.     对依赖对象进行行为增强

    所谓AOP,就是Aspect Oriented Programming(面向方面的编程),核心思想是把一个“方面”独立出来,从而实现组件间的松耦合。也许有些晦涩难懂,所以我们还是看个简单的例子。

    在我们的银行依赖中,假设有个需求,即在每一笔取款业务的前后都要输出日志信息。因此我们需要这样修改我们的代码:

    public class BankICBC implements Bank {

        private static Logger logger = Logger.getLogger(Bank.class.getName());

     

        @Override

        public Cash withDraw(DepositBook depositBook, BigDecimal amount) {

            logger.log(Level.INFO, "withdraws starting...");

            // ……

            logger.log(Level.INFO, "withdraws ended…");

        }

    }

     
     

    可以看到,我们为了实现这个需求需要在其中加入定义logger、输出日志等代码。而这些代码,就是我们所说的独立的“方面”。为什么这么说呢?因为日志的输出工作,是与开发者真正要做的取款业务完全没有关系的。再假设,如果我们需要在很多其它地方也要做同样的日志处理,而这样的处理又完全不依赖于那些地方的逻辑,则我们需要打开全部的代码页,不分情况的Ctrl+C和Ctrl+V,这无疑给开发和维护带来了不小的困扰。

    因此AOP的出现,就可以将这个独立的日志处理的“方面”从实际的依赖对象里分离开来,而在依赖对象在运行的时候,这个“方面”又可以加到依赖对象身上得以运行,也就是我们所说的依赖对象的行为被增强了,因为它的行为不但实现了它本身的逻辑,而且也实现了被增强的其它“方面”的逻辑。而在AOP体系内,用以将其它“方面”的逻辑增强到某对象上的组件往往被称作Interceptor(拦截器)。

    Spring、Seam和Guice都提供了相应的拦截器定义方式,由于Seam是基于原注解模式的定义方法,在开发者使用时稍有不便,因此我们这里以Spring为例简单介绍一下如何将刚才的“日志处理方面”应用到我们的程序当中。

    首先我们将“日志处理方面”分离出来作为一个独立的类,这个类即是被独立出来的“方面”。


     

    public class LogInterceptor {

        private static Logger logger = Logger.getLogger(LogInterceptor.class.getName());

       

        public Object log(ProceedingJoinPoint call) throws Throwable {

            logger.log(Level.INFO, "withdraws starting...");

            try {

                return call.proceed();

            } finally {

                logger.log(Level.INFO, "withdraws ended...");

            }

        }

    }

     
     

    Spring提供了很多种拦截器组装方式,这里我们采用XML配置的方式将这个“方面”增强到我们的银行依赖对象上:

    <beans>

      <!-- …… -->

     

      <!-- 这里将“方面”类声明为Spring管理的依赖 -->

      <bean id="logger" class="tutorial.di.ch01.LogInterceptor"/>

     

      <!-- 这里将所声明的“方面”增强到需要的地方 -->

      <aop:config>

          <aop:aspect ref="logger">

              <aop:pointcut id="pointcuts.withdrawMethod"

                  expression="execution(* tutorial.di.ch01.BankICBC.withDraw(..))" />

              <aop:around pointcut-ref="pointcuts.withdrawMethod " method="log"/>

          </aop:aspect>

      </aop:config>

    </beans>

     
     

    此后原先的BankICBC类就不需要再写任何的关于日志输出的代码,就可以将该功能导入进来了。反之如果想去掉这个需求,同样不需要变更BankICBC类,只将拦截器的配置删除即可,从而大大降低了程序逻辑与其它“方面”的耦合度。

    注意所有AOP功能的底层实现都是靠Java的动态代理机制实现的,往往是基于JDK自身的代理类,或者是Javassist、CGLIB工具等,因此AOP的作用对象不能是私有方法、静态方法以及final方法。

  • 相关阅读:
    SQLyog使用中的点滴总结
    Maven的GroupID和ArtifactID的含义
    Android View 深度分析requestLayout、invalidate与postInvalidate
    15 个 Android 通用流行框架大全
    Android Studio中获取查看签名SHA1证书指纹数据或MD5的方法
    android:descendantFocusability用法简析
    Android应用层View绘制流程与源码分析
    android.graphic.Path
    Android Scroller简单用法
    Android 2D Graphics学习 Region和Canvas裁剪
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4173338.html
Copyright © 2011-2022 走看看