第3章 创建切面

1AOP介绍

大多数AOP定义都是关于如何使交叉业务模块化

应用系统分成多个模块,每个模块的主要业务是为它的特殊领域提供服务。然而,每个模块也需要一些相似的辅助功能,如安全和事务管理。重要通用功能的常用面向对象技术是使用继承和委托模式。但由于基础类在系统中到处使用,使用继承会引起脆弱的继承关系,委托模式比较笨拙,依然需要重复调用委托对象

在多数情况下,AOP是一种简单的替代方法。使用AOP,在一个地方定义通用功能,只是声明式定义何时何地使用这些功能,而不需要再需要新功能的地方修改代码。交叉业务现在可以被模块化到特定对象切面中。这样做,有两个好处:第一,现在每个业务逻辑放在一个地方,而不是分散到代码的各个角落。第二,服务模块更加清晰,因为他们只包含他们的核心功能,辅助功能转移到切面中

1.1、定义AOP术语

切面:要实现的交叉功能

连接点:连接点是应用程序执行过程中插入切面的地点,这个地点可以是方法调用,异常抛出。切面代码在这些地方插入到你的应用流程中,添加新的功能

通知:切面的实际实现

切入点:定义了通知应该应用在哪些连接点。通过指定类名和方法名,或者匹配类名和方法名式样的正则表达式来指定切入点

引入:引入允许为已存在的类添加新的方法和属性

目标对象:目标对象是被通知对象。如果没有AOP,这个类就必须要包含它的主要逻辑以及其他交叉业务逻辑。有了AOP,目标对象就可以全身心的关注主要业务,忘记应用其上的通知

代理:代理是将通知应用到目标对象后创建的对象。对于客户对象来说,目标对象和代理对象是一样的,应用程序的其他部分不用为了支持代理对象而改变

织入:织入是将切面应用到目标对象从而创建一个新的代理对象的过程。切面在指定接入点被织入目标对象。织入发生在目标对象生命周期的多个点上:

编译期:切面在目标对象编译时织入

类转载期:切面在目标对象被载入到JVM中时织入

运行期:切面在应用系统运行时织入。通常,AOP容器将在织入切面的时候动态生成委托目标对象的代理对象

1.2SpringAOP实现

Spring中,所有的切入点都以Java类的形式编写

切入点通常编写在Spring的配置文件中

Spring在运行期间创建代理对象

Spring有两种代理创建方式:

如果目标对象实现了一个接口,Spring使用JDKProxy类创建代理。这个类让Spring动态产生一个新的类,它实现了所需的接口,织入了通知,并且代理对目标对象的所有请求

如果目标对象没有实现任何接口,Spring使用CGLIB库生成目标对象的子类。在创建这个子类的时候,Spring将通知织入,并且将目标对象的调用委托给这个子类

Spring只支持方法连接点

2、创建通知

通知包含了切面的逻辑。创建一个通知对象的时候,是在编写实现交叉功能的代码。Spring的连接点模型是建立在方法拦截上。编写的Spring通知会在方法调用周围的各个地方织入系统中。因为Spring在方法执行的多个地方织入通知,所以有多种通知类型

2.1、前置通知

扩展MethodBeforeAdvice接口

public interface MethodBeforeAdvice{

    void before(Method method,Object[] args,Object target)

    throws Throwable

}

这个接口为我们提供了获得目标方法、参数以及目标对象的机会。方法返回后目标方法将被调用

ProxyFactoryBean类是在BeanFactoryApplicationContext中用来显式创建代理类对象的中心类。给它提供一个要实现的接口、一个要代理的目标对象、一个要织入的通知,它将创建一个崭新的代理对象

2.2、后置通知

实现MethodAfterAdvice接口

2.3、环绕通知

MethodInterceptor接口提供了在一个通知对象中实现前置通知和后置通知的能力

2.4、异常通知

ThrowsAdvice接口定义在异常发生时该有什么动作

2.5、引入通知

引入通知给目标对象添加新的方法以及属性

3、定义切入点

切入点决定了一个特定类的特定方法是否满足一条特定规则。如果一个方法确实符合,通知就应用到该方法上

3.1、在Spring中定义切入点

Spring根据需要织入通知的类和方法来定义切入点。通知是根据他们的特性织入目标类和方法的,如类名和方法签名

Spring切入点框架的核心接口是Pointcut接口

public interface Pointcut {

ClassFilter getClassFilter();

MethodMatcher getMethodMatcher();

}

ClassFilter决定一个类是否符合通知的要求

public interface ClassFilter {

boolean matches(Class clazz);

}

实现这个接口的类决定了以参数形式传入进来的类是否应该被通知

MethodMatcher接口通过方法过滤切面

public interface MethodMatcher {

boolean matches(Method m, Class targetClass);

public boolean isRuntime();

public boolean matches(Method m, Class target, Object[] args);

}

matches(Method m, Class targetClass)方法根据目标类和方法决定一个方法是否给被通知,因为可以静态的判断,所以可以在AOP代理被创建的时候调用一次这个方法。这个方法的结果最终决定了通知是否被织入

如果matches(Method m, Class targetClass)方法返回tureisRuntime()用来决定MethodMatcher的类型,有两种类型:静态和动态。静态切入点的意思是通知总是被执行。如果一个切入点是静态的,isRuntime()方法应该返回false。动态切入点根据运行时方法的参数值决定通知是否需要执行。如果一个切入点是动态的,isRuntime()方法应该返回tureisRuntime()方法在代理类创建时调用一次

对于动态切入点,目标对象方法每次被调用的时候,matches(Method m, Class target, Object[] args)方法被调用

3.2、理解Advisor

大多数切面是由定义切面行为的通知和定义切面和什么地方执行的切入点如何而成的

大多数Spring自带的切入点都有一个对应的PointcutAdvisor,方便在一个地方定义切入点和通知

    public interface PointcutAdvisor {

Pointcut getPointcut();

Advice getAdvice();

}

4、创建引入

其他类型通知是在方法调用的周围织入到不同的连接点。而引入则是影响整个类。他们通过给需要消息的类添加方法和属性来实现。也就是说,用一个已经存在的类让它实现另外的接口,维持另外的状态

4.1、实现IntroductionInterceptor

Spring通过特殊的方法拦截器接口IntroductionMethodInterceptor接口来实现引入

引入通知为对象添加了新的接口和新的属性

5、使用ProxyFactoryBean

ProxyFactoryBean创建代理对象

6、自动代理

对于小型应用系统,可以使用ProxyFactoryBean创建代理对象,因为没有许多类需要通知

Spring有一种自动代理机制,可以让容器产生代理

7、小结

AOP是面向对象编程的一个有力补充。有了切面,可以将从前分散在应用系统中的功能重组变成可重用组件。现在可以采用声明方式或编码方式来定义这些功能应用到哪里,以及如何使用。这样减少了重复代码,并且将代码专注于它的主要功能上

Spring提供了一个AOP框架,能够将切面添加到方法执行的周围。可以在方法调用的前面,后面以及周围织入通知,也可以为异常处理添加定制行为

使用Spring的切入点机制定义在哪里将通知织入应用系统。一般会使用Spring预定义的静态切入点

除了在方法周围添加通知之外,引用能够为应用对象添加新的方法和属性。引用可以动态创建复合对象,给予多继承一样的能力

Spring提供了多种方便的创建代理对象的方法,使用ProxyFactoryBean,可以完全掌握代理的创建。当使用自动代理时,也有许多灵活的控制方法

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值