依赖注入及AOP简述(十二)——依赖注入对象的行为增强(AOP)

前端之家收集整理的这篇文章主要介绍了依赖注入及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方法

原文链接:https://www.f2er.com/javaschema/287113.html

猜你在找的设计模式相关文章