深入理解spring的AOP机制原理

网友投稿 212 2023-04-07


深入理解spring的AOP机制原理

前言

在软件开发中,散布于应用中多处的功能被称为横切关注点,通常来讲,这些横切关注点从概念上是与应用的业务逻辑相分离的。把这些横切关注点和业务逻辑分离出来正是AOP要解决的问题。AOP能够帮我们模块化横切关注点,换言之,横切关注点可以被描述为影响应用多出的功能。这些横切点被模块化特殊的类,这些类被称为切面。

术语定义

通知:切面有必须要完成的工作,在AOP中,切面的工作被称为通知。通知定义了切面是什么以及何时使用,除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题,它应该在某个方法之前?之后?之前和之后都调用?还是只在方法抛出异常时调用?

连接点:连接点是应用程序执行过程中,能够插入切面的一个点。

切点:是在连接点的基础上定义切点,比方说一个类由十几个方法,每个方法的调用前和调用后都可以插入通知,但是你只想选择几个方法插入通知,因此你定义一个切点来选择你想插入的通知的方法。

切面:切面就是通知和切点的结合。

织入:织入是把切面应用到目标对象并创建新的代理对象的过程,切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以进行织入:编译期、类加载期、运行期。其中编译器织入需要特殊的编译器,类加载器织入需要特殊的类加载器,spring的AOP 是在运行期织入通知的。

Spring的AOP支持

spring提供了AOP的四种支持,分别是:基于代理的经典Spring AOP模式;纯POJO切面;@AspectJ注解驱动的切面;@注入式AspectJ切面。spring所创建的通知都是用标准的java类编写的,而且定义通知所应用的切点通常会使用注解或在Spring配置文件里采用XML来编http://写。

spring只支持方法级别的连接点。

在spring AOP中,要使用AspectJ的切点表达式语言来定义切点,关于Spring AOP的AspectJ切点,最重要的一点就是Spring仅支持AspectJ切点指示器的一个子集:

1.arg() 限制连接点匹配参数为指定类型的执行方法;

2.@args() 限制连接点匹配参数由指定注解标注的执行方法;

3.execution() 用于匹配是连接点的执行方法;

4.this() 限制连接点匹配AOP代理的bean引用为指定类型的类

5.target 限制连接点匹配目标对象为指定类型的类

6.@target() 限制连接点匹配特定的执行对象,这些对象对应的类要具有指定类型的注解

7.within() 限制连接点匹配指定的类型

8.@within() 限制连接点匹配特定注解所标注的类型

9.@annotation 限定匹配带有指定注解的连接点

spring 注解创建切面

目标对象:

package concert;

public interface Performance{

public void perform();

}

切面对象:

package concert;

@Aspect//表示Audience的实例是一个切面

public class Audience{

@Before("execution(**concert.Performance.perform(..))")

public void silenceCellPhones(){

//在perfrom方法执行之前

}

@Before("execution(**concert.Performance.perform(..))")

public void takeSeats(){

//在perfrom方法执行之前

}

@AfterReturning("execution(**concert.Performance.perform(..))")

public void silenceCellPhones(){

//在perfrom方法执行之后

}

@AfterThrowing("execution(**concert.Performance.perform(..))")

public void silenceCellPhones(){

//在perfrom方法抛出异常之后

}

}

上面的类中切点表达式execution(**concert.Performance.perform(..))多次出现,我们也可以通过@Pointcut注解避免每次都写很长的切点表但是如下所示:

@Aspect//表示Audience的实例是一个切面

public class Audience{

@Pointcut("execution(**concert.Performance.perform(..))")

public void performance(){}

@Before("performance()")

public void silenceCellPhones(){

//在perfrom方法执行之前

}

@Before("performance()")

public void takeSeats(){

//在perfrom方法执行之前

}

@AfterReturning("performance()")

public void silenceCellPhones(){

//在perfrom方法执行之后

}

@AfterThrowing("performance()")

public void silenceCellPhones(){

//在perfrom方法抛出异常之后

}

}

接下来需要在配置文件中配置切面如下所示:

@Configuration

@EnableAspectJAutoProxy//启动AspectJ自动代理

@ComponentScan

public class ConcertConfig{

}

//或者在配置文件中配置中添加

表示启动切面代理

环绕通知:

@Aspect//表示Audience的实例是一个切面

public class Audience{

@Pointcut("execution(**concert.Performance.perform(..))")

public void performance(){}

@Before("performance()")

public void watchPerformance(ProceedingJoinPoint jp){

//在方法之前执行

System.out.println(" beform the method is invoked");

jp.proceed()//控制权交给目标方法

//在方法之后执行

System.out.println(" after the method is invoked");

}

}

处理通知中的参数

public class Audience{

@Pointcut("execution(**concert.Performance.perform(int))&&args(trackNumber)")

public void performance(){}

@Before("performance(trackNumber)")

public void watchPerformance(int trackNumber){

//截获传递给目标方法的参数并传递给切面中处理方法

System.out.println(trackNumber);

}

}

xml中声明切面

spring AOP提供的xml配置元素:

1. 定义AOP通知;

2. 后置通知;

3. 返回通知

4. 环绕通知

5. 定义一个切面

6. 启用切面注解驱动

7. 前置通知

8. 顶层的AOP配置元素;

9.:定义个切点

pointcut="execution(**concert.Performance.perform())" method="silenceCellPhones"/>

pointcut="execution(**concert.Performance.perform())" method="takeSeats"/>

pointcut="execution(**concert.Performance.perform())" method="applause"/>

pointcut="execution(**concert.Performance.perform())" method="demandRefund"/>

定义切点:

pointcut-ref="performance" method="silenceCellPhones"/>

pointcut="performance" method="takeSeats"/>

pointcut="performance" method="applause"/>

pointcut="performance" method="demandRefund"/>

pointcut="execution(**concert.Performance.perform())" method="silenceCellPhones"/>

pointcut="execution(**concert.Performance.perform())" method="takeSeats"/>

pointcut="execution(**concert.Performance.perform())" method="applause"/>

pointcut="execution(**concert.Performance.perform())" method="demandRefund"/>

定义切点:

pointcut-ref="performance" method="silenceCellPhones"/>

pointcut="performance" method="takeSeats"/>

pointcut="performance" method="applause"/>

pointcut="performance" method="demandRefund"/>

pointcut="execution(**concert.Performance.perform())" method="takeSeats"/>

pointcut="execution(**concert.Performance.perform())" method="applause"/>

pointcut="execution(**concert.Performance.perform())" method="demandRefund"/>

定义切点:

pointcut-ref="performance" method="silenceCellPhones"/>

pointcut="performance" method="takeSeats"/>

pointcut="performance" method="applause"/>

pointcut="performance" method="demandRefund"/>

pointcut="execution(**concert.Performance.perform())" method="applause"/>

pointcut="execution(**concert.Performance.perform())" method="demandRefund"/>

定义切点:

pointcut-ref="performance" method="silenceCellPhones"/>

pointcut="performance" method="takeSeats"/>

pointcut="performance" method="applause"/>

pointcut="performance" method="demandRefund"/>

pointcut="execution(**concert.Performance.perform())" method="demandRefund"/>

定义切点:

pointcut-ref="performance" method="silenceCellPhones"/>

pointcut="performance" method="takeSeats"/>

pointcut="performance" method="applause"/>

pointcut="performance" method="demandRefund"/>

pointcut-ref="performance" method="silenceCellPhones"/>

pointcut="performance" method="takeSeats"/>

pointcut="performance" method="applause"/>

pointcut="performance" method="demandRefund"/>

pointcut="performance" method="takeSeats"/>

pointcut="performance" method="applause"/>

pointcut="performance" method="demandRefund"/>

pointcut="performance" method="applause"/>

pointcut="performance" method="demandRefund"/>

pointcut="performance" method="demandRefund"/>


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java 中Excel转shape file的实例详解
下一篇:WebStorm ES6 语法支持设置&babel使用及自动编译(详解)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~