四、依赖注入对象的行为增强(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方法。

依赖注入及AOP简述(十二)——依赖注入对象的行为增强(AOP) .的更多相关文章

  1. aop学习总结二------使用cglib动态代理简单实现aop功能

    aop学习总结二------使用cglib动态代理简单实现aop功能 模拟业务需求: 1.拦截所有业务方法 2.判断用户是否有权限,有权限就允许用户执行业务方法,无权限不允许用户执行业务方法 (判断是 ...

  2. 依赖注入及AOP简述(二)——工厂和ServiceLocator .

    2.2.    工厂模式 基于手工构建组件的诸多弱点,1995年“大师4人组”(GoF)在其经典著作<DesignPatterns>一书中提出了“工厂模式”,这种模式在一定程度上有效的解决 ...

  3. WPF入门教程系列十二——依赖属性(二)

    二. 依赖属性的优先级 由于WPF 允许我们可以在多个地方设置依赖属性的值,所以我们就必须要用一个标准来保证值的优先级别.比如下面的例子中,我们在三个地方设置了按钮的背景颜色,那么哪一个设置才会是最终 ...

  4. 【十二】注入框架RoboGuice使用:(Your First Injected ContentProvider)

    上一篇我们简单的介绍了一下RoboGuice的使用([十一]注入框架RoboGuice使用:(Your First Injection into a Custom View class)),今天我们来 ...

  5. Spring Aop(十二)——编程式的创建Aop代理之AspectjProxyFactory

    转发地址:https://www.iteye.com/blog/elim-2397922 编程式的创建Aop代理之AspectjProxyFactory 之前已经介绍了一款编程式的创建Aop代理的工厂 ...

  6. 【emWin】例程二十二:窗口对象——Framewin

    简介: 框架窗口为您的应用提供一个PC 应用程序的窗口外观.这些窗口由周围框架.标题栏和用户区组成. 触摸校准(上电可选择是否进入校准界面) 截图 实验指导书及代码包下载: 链接:http://pan ...

  7. 【emWin】例程三十二:窗口对象———Progbar

    简介: 进度条通常在应用程序中用于实现虚拟化:本例程实现液晶亮度显示 . 触摸校准(上电可选择是否进入校准界面) 实验现象: 实验指导书及代码包下载: 链接:http://pan.baidu.com/ ...

  8. ASP入门(十二)-Application对象

    在一起协同工作以完成某项任务的一组ASP文件称为一个应用程序.Application 对象用于把这些文件捆绑在一起. Application 对象用于在整个应用程序生存期间保存信息. Applicat ...

  9. C++(三十二) — 常对象、常成员变量、常成员函数

    常量:对于既需要共享.又需要防止改变的数据.在程序运行期间不可改变. const 修饰的是对象中的 this 指针.所以不能被修改. 1.常对象 数据成员值在对象的整个生存期内不能改变.在定义时必须初 ...

  10. Sql注入_mysql盲注__二次注入

    sleep盲注攻击 Sleep延迟:延迟盲注 If(条件,true,false): 条件成立,返回第二个参数,反之第三个参数 举例1:length id=1 union select 1,2,slee ...

随机推荐

  1. Android学习总结——Activity之间传递参数

    核心内容:一.在 Activity 之间传递简单数据二.在 Activity 之间传递复杂数据 三.在 Activity 之间传递自定义值对象   软件环境:Android Studio   一.在 ...

  2. optimizer for eclipse--Eclipse优化,让你的Eclipse快来飞!

    官方网站:http://zeroturnaround.com/free/optimizer-for-eclipse/ infoq网址:http://www.infoq.com/cn/news/2015 ...

  3. android同时使用多个library时的问题

    剧情是这样,我的app要使用四个library,如:LibraryA,LibraryB.这两个库又都需要support.v4.jar. 由于加载的时间不同,所以四个support.v4.jar不同,出 ...

  4. PipedInputStream/PipedOutputStream原理

    PipedInputStream类与PipedOutputStream类用于在应用程序中创建管道通信.一个PipedInputStream实例对象必须和一个PipedOutputStream实例对象进 ...

  5. IDE idea 更换项目的JDK步骤

    1.如图:

  6. C#整理3——运算符和语句

    运算符: 一.算术运算符:+ - * / % ——取余运算 取余运算的应用场景:1.奇偶数的区分. 2.把数变化到某个范围之内.——彩票生成. 3.判断能否整除.——闰年.平年. using Syst ...

  7. 在CSDN上看到的一个过滤方法,感觉还不错

    /// <summary> /// 把字符串中包含的敏感词替换成别的关键字 /// </summary> /// <param name="s"> ...

  8. JS实现简单倒计时

    /*倒计时*/ lcf.downTime = function (endTime,obj,callback){ /*基本判断*/ if(!endTime || typeof endTime !== & ...

  9. 详解 CSS 属性 - 伪类和伪元素的区别(再也不用概念盲了!!!)

    首先,阅读 w3c 对两者的定义: CSS 伪类用于向某些选择器添加特殊的效果. CSS 伪元素用于将特殊的效果添加到某些选择器. 可以明确两点,第一两者都与选择器相关,第二就是添加一些“特殊”的效果 ...

  10. JS功能代码集锦

    只作 说明 逻辑用 1.模仿fade in(),fade out(). 原理:setInterval ( "opacity++透明度“函数,时间间隔) var alpha = 0; func ...