Spring AOP简述

2017-08-07  本文已影响0人  守望者00

什么是AOP

Aspect Oriented Programming:面向切面编程

什么时候会出现面向切面编程的需求?

按照软件重构的思想,如果多个类中出现重复的代码,就应该考虑定义一个共同的抽象类,将这些共同的代码提取到抽象类中,比如Teacher,Student都有username,那么就可以把username及相关的get、set方法抽取到SysUser中,这种情况,我们称为纵向抽取。

但是如果,我们的情况是以下情况,又该怎么办?

给所有的类方法添加性能检测,事务控制,该怎么抽取?

PerformanceMonitor

TransactionManager

AOP就是希望将这些分散在各个业务逻辑代码中的相同代码,通过横向切割的方式抽取到一个独立的模块中,让业务逻辑类依然保存最初的单纯。

抽取出来简单,难点就是如何将这些独立的逻辑融合到业务逻辑中,完成跟原来一样的业务逻辑,这就是AOP解决的主要问题。

AOP术语

l连接点(Joinpoint)

程序执行的某个特定位置,如某个方法调用前,调用后,方法抛出异常后,这些代码中的特定点称为连接点。简单来说,就是在哪加入你的逻辑增强

l切点(PointCut

每个程序的连接点有多个,如何定位到某个感兴趣的连接点,就需要通过切点来定位。

比如,连接点--数据库的记录,切点--查询条件

l增强(Advice

增强是织入到目标类连接点上的一段程序代码。

在Spring中,像BeforeAdvice等还带有方位信息

l目标对象(Target

需要被加强的业务对象

l织入(Weaving

织入就是将增强添加到对目标类具体连接点上的过程。

l代理类(Proxy

一个类被AOP织入增强后,就产生了一个代理类。

l切面(Aspect

切面由切点和增强组成,它既包括了横切逻辑的定义,也包括了连接点的定义,SpringAOP就是将切面所定义的横切逻辑织入到切面所制定的连接点中。

userBiz add update del

couseBiz add update del

定义一个范围给哪些类的哪些方法

增强:加事务的控制

AOP实现者

lAspectJ

AspectJ是语言级的AOP实现,2001发布,扩展了Java语言,定义了AOP语法,能够在编译期通过提供横切代码的织入,所以它有一个专门的编译器用来生成遵守Java字节码规范的class文件

lSpringAOP

SpringAOP使用纯Java实现,在运行期通过代理的方式向目标类织入增强代码。

SpringAOP代理机制

基于JDK的动态代理,接口

基于CGlib的动态代理,类

问题

现有一个UserDao的实现,想在原有的实现基础上添加新的业务处理,怎么办?

假如有多个实现

什么是代理模式

我们假设有一个UserDao和一个TransactionManager类

静态代理的问题:

1,假如还有其他的dao,则还需要再创建新的proxy

2,如果目标对象的方法发生改变,比如方法名做了修改,则代理类也要做修改

基于JDK的动态代理

关键类:

InvocationHandler:其作用就是将横切逻辑代码和业务逻辑代码编织到一起的编织器。

Proxy则通过newProxyInstance根据handler来创建一个符合第三方接口的代理类

基于接口的模式

基于CGlib的动态代理

CGlib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截技术拦截所有父类方法的调用,并织入横切逻辑

扩展

如果要多层怎么办?

AOP小结

这种实现方式存在三个明显需要改进的地方:

1.目标类的所有方法都添加了性能监视横切逻辑,而有时,这并不是我们所期望的,我们可能只希望对业务类中的某些特定方法添加横切逻辑;

2.我们通过硬编码的方式指定了织入横切逻辑的织入点,即在目标类业务方法的开始和结束前织入代码;

3.我们手工编写代理实例的创建过程,为不同类创建代理时,需要分别编写相应的创建代码,无法做到通用。

Spring AOP的主要工作就是围绕以上三点展开:Spring

AOP通过Pointcut(切点)指定在哪些类的哪些方法上织入横切逻辑,通过Advice(增强)描述横切逻辑和方法的具体织入点(方法前、方法后、方法的两端等)。此外,Spring通过Advisor(切面)将Pointcut和Advice两者组装起来。有了Advisor的信息,Spring就可以利用JDK或CGLib的动态代理技术采用统一的方式为目标Bean创建织入切面的代理对象了。

创建增强

Spring使用增强类定义横切逻辑,同时由于Spring只支持方法连接点,增强还包括了在方法的哪一点加入横切代码的方位信息,所以增强既包含横切逻辑,还包含部分连接点的信息

增强类型

AOP联盟为增强定义了org.aopalliance.aop.Advice接口,Spring支持5种类型的增强

前置增强:org.springframework.aop.BeforeAdvice代表前置增强,因为Spring只支持方法级的增强,所以MethodBeforeAdvice是目前可用的前置增强,表示在目标方法执行前实施增强,而BeforeAdvice是为了将来版本扩展需要而定

后置增强:org.springframework.aop.AfterReturningAdvice代表后增强,表示在目标方法执行后实施增强;

环绕增强:org.aopalliance.intercept.MethodInterceptor代表环绕增强,表示在目标方法执行前后实施增强;

异常抛出增强:org.springframework.aop.ThrowsAdvice代表抛出异常增强,表示在目标方法抛出异常后实施增强;

案例:

创建切面

我们可能注意到一个问题:增强被织入到目标类的所有方法中,假设我们希望有选择地织入到目标类某些特定的方法中,就需要使用切点进行目标连接点的定位了。描述连接点是进行AOP编程最主要的工作

增强提供了连接点方位信息:如织入到方法前面、后面等,而切点进一步描述织入到哪些类的哪些方法上。

Spring通过org.springframework.aop.Pointcut接口描述切点,Pointcut由ClassFilter和MethodMatcher构成,它通过ClassFilter定位到某些特定类上,通过MethodMatcher定位到某些特定方法上,这样Pointcut就拥有了描述某些类的某些特定方法的能力。

Spring使用org.springframework.aop.Advisor接口表示切面的概念,一个切面同时包含横切代码和连接点信息

从广义上说,增强其实就是一种最简单的切面,它既包括横切代码也包括切点信息,只不过它的切点只是简单的方法相对位置的信息。所以增强一般需要和切点联合才可以表示一个更具实用性的切面。

AspectJ

Spring AOP,它包括基于XML配置的AOP和基于@AspcetJ注解的AOP,这两种方法虽然在配置切面时的表现方式不同,但底层都是采用动态代理技术(JDK代理或CGLib代理)。Spring可以集成AspectJ,但AspectJ本身并不属于Spring AOP的范畴。

Spring在处理@Aspect注解表达式时,需要将Spring的asm模块添加到类路径中。asm是轻量级的字节码处理框架,因为Java的反射机制无法获取入参名,Spring就利用asm处理@AspectJ中所描述的方法入参名。

也可以通过配置的方式来生成代理对象

工作原理:

首先,在配置文件中引入aop命名空间,然后通过aop命名空间的自动为Spring容器中那些匹配@AspectJ切面的Bean创建代理,完成切面织入。

上一篇下一篇

猜你喜欢

热点阅读