深入理解spring的AOP机制原理

前言

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

术语定义

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

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

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

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

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

Spring的AOP支持

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

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{
}
//或者在配置文件中配置中添加
<aop:aspectj-autoproxy />

表示启动切面代理

环绕通知:

@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:advisor> 定义AOP通知;
2.<aop:after> 后置通知;
3.<aop:after-returning> 返回通知
4.<aop:around> 环绕通知
5.<aop:aspect> 定义一个切面
6.<aop:aspectj-autoproxy> 启用切面注解驱动
7.<aop:before> 前置通知
8.<aop:config> 顶层的AOP配置元素;
9.<aop:pointcut>:定义个切点

<aop:config>
  <aop:aspect ref="audience">
    <aop:before
     pointcut="execution(**concert.Performance.perform())" method="silenceCellPhones"/>
     <aop:before
     pointcut="execution(**concert.Performance.perform())" method="takeSeats"/>
     <aop:after-returning
     pointcut="execution(**concert.Performance.perform())" method="applause"/>
     <aop:after-throwing
     pointcut="execution(**concert.Performance.perform())" method="demandRefund"/>

  </aop:aspect>
</aop config>

定义切点:

<aop:config>
  <aop:aspect ref="audience">
    <aop:pointcut id="performance" expression="execution(**concert.Performance.perform())">
    <aop:before
     pointcut-ref="performance" method="silenceCellPhones"/>
     <aop:before
     pointcut="performance" method="takeSeats"/>
     <aop:after-returning
     pointcut="performance" method="applause"/>
     <aop:after-throwing
     pointcut="performance" method="demandRefund"/>

  </aop:aspect>
</aop config>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Spring AOP的实现原理详解及实例

    Spring AOP的实现原理详解及实例 spring 实现AOP是依赖JDK动态代理和CGLIB代理实现的. 以下是JDK动态代理和CGLIB代理简单介绍 JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理. CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类.CGLIB是高效的代码生成包,底层是依靠ASM(开源的Java字节码编辑类库)操作字节码实现的,性能比JDK强. 在Spring中

  • java Spring AOP详解及简单实例

    一.什么是AOP AOP(Aspect Oriented Programming)面向切面编程不同于OOP(Object Oriented Programming)面向对象编程,AOP是将程序的运行看成一个流程切面,其中可以在切面中的点嵌入程序. 举个例子,有一个People类,也有一个Servant仆人类,在People吃饭之前,Servant会准备饭,在People吃完饭之后,Servant会进行打扫,这就是典型的面向切面编程. 其流程图为: 二.Spring AOP实现: 1.People

  • 基于spring中的aop简单实例讲解

    aop,即面向切面编程,面向切面编程的目标就是分离关注点,比如:一个骑士只需要关注守护安全,或者远征,而骑士辉煌一生的事迹由谁来记录和歌颂呢,当然不会是自己了,这个完全可以由诗人去歌颂,比如当骑士出征的时候诗人可以去欢送,当骑士英勇牺牲的时候,诗人可以写诗歌颂骑士的一生.那么骑士只需要关注怎么打仗就好了.而诗人也只需要关注写诗歌颂和欢送就好了,那么这样就把功能分离了.所以可以把诗人当成一个切面,当骑士出征的前后诗人分别负责欢送和写诗歌颂(记录).而且,这个切面可以对多个骑士或者明人使用,并不只局

  • Spring AOP 动态多数据源的实例详解

     Spring AOP 动态多数据源的实例详解 当项目中使用到读写分离的时候,我们就会遇到多数据源的问题.多数据源让人最头痛的,不是配置多个数据源,而是如何能灵活动态的切换数据源.例如在一个spring和Mybatis的框架的项目中,我们在spring配置中往往是配置一个dataSource来连接数据库,然后绑定给sessionFactory,在dao层代码中再指定sessionFactory来进行数据库操作. 正如上图所示,每一块都是指定绑死的,如果是多个数据源,也只能是下图中那种方式. 可看

  • Spring AOP 基于注解详解及实例代码

    Spring AOP  基于注解详解及实例代码 1.启用spring对@AspectJ注解的支持: <beans xmlns:aop="http://www.springframework.org/schema/aop"...> <!--启动支持--> <aop:aspectj-autoproxy /> </beans> 也可以配置AnnotationAwareAspectJAutoProxyCreator Bean来启动Spring对@

  • Spring AOP 自定义注解的实现代码

    1.在Maven中加入以下以依赖: <!-- Spring AOP + AspectJ by shipengzhi --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>3.0.6.RELEASE</version> </dependency> <

  • 利用spring AOP记录用户操作日志的方法示例

    前言 最近项目已经开发完成,但发现需要加用户操作日志,如果返回去加也不太现实,所以使用springAOP来完成比较合适.下面来一起看看详细的介绍: 注解工具类: @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface LogAnnotation { String operateModelNm() default ""; String operateFuncNm() default

  • 关于spring中aop的注解实现方法实例详解

    前言 在之前的一篇文章中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢.前面已经讲过aop的简单理解了,这里就不在赘述了.话不多说,来一起看看详细的介绍: 注解方式实现aop我们主要分为如下几个步骤: 1.在切面类(为切点服务的类)前用@Aspect注释修饰,声明为一个切面类. 2.用@Pointcut注释声明一个切点,目的是为了告诉切面,谁是它的服务对象.(此注释修饰的方法的方法体为空,不需要写功能比如 public void say(){};就可以了,方法名可以被候命

  • 深入理解spring的AOP机制原理

    前言 在软件开发中,散布于应用中多处的功能被称为横切关注点,通常来讲,这些横切关注点从概念上是与应用的业务逻辑相分离的.把这些横切关注点和业务逻辑分离出来正是AOP要解决的问题.AOP能够帮我们模块化横切关注点,换言之,横切关注点可以被描述为影响应用多出的功能.这些横切点被模块化特殊的类,这些类被称为切面. 术语定义 通知:切面有必须要完成的工作,在AOP中,切面的工作被称为通知.通知定义了切面是什么以及何时使用,除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题,它应该在某个方法之前

  • 彻底理解Spring注解@Autowired实现原理

    目录 前言 1.@Autowired注解用法 2.@Autowired注解的作用到底是什么 3.@Autowired注解是如何实现的 自己实现一个注解 4.@Autowired注解实现逻辑分析 5.问题 5.1.注解的有效周期是什么? 5.2.注入的bean和用它的bean的关系是如何维护的? 5.3.为什么注入的bean不能被定义为static的? 前言 使用spring开发时,进行配置主要有两种方式,一是xml的方式,二是java config的方式. spring技术自身也在不断的发展和改

  • 深入浅析Spring 的aop实现原理

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合.当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力.也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系.例如日志功能.日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无

  • Spring RabbitMQ死信机制原理实例详解

    死信队列:没有被及时消费的消息存放的队列,消息没有被及时消费有以下几点原因: 1.有消息被拒绝(basic.reject/ basic.nack)并且requeue=false 2.队列达到最大长度 3.消息TTL过期 采用死信机制的好处是可以提高系统的稳定性,当消息消费失败后,消息进入死信队列,可以对消息进行补偿,可以达到最终一致性的目标. 具体例子如下: @Bean public Queue deadQueue() { return new Queue(DEAD_QUEUE_NAME, tr

  • Spring Cloud 中自定义外部化扩展机制原理及实战记录

    目录 自定义PropertySource 扩展PropertySourceLocator Spring.factories 编写controller测试 阶段性总结 SpringApplication.run PropertySourceBootstrapConfiguration.initialize ApplicationContextInitializer的理解和使用 创建一个TestApplicationContextInitializer 添加spi加载 Spring Cloud针对E

  • Spring IOC和aop的原理及实例详解

    这篇文章主要介绍了Spring IOC和aop的原理及实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架.特点是面向接口编程,松耦合. 1:IOC(控制反转) 别名(DI:依赖注入) 首先来一段ioc的实现原来代码: public class ClassPathXmlApplicationContext implements BeanFactory { privat

  • Spring中AOP概念与两种动态代理模式原理详解

    目录 1.概念 1.AOP技术简介 2.AOP的优势 3.Spring AOP术语 4.AOP 开发明确的事项 2.AOP底层实现 1.AOP 的动态代理技术: 3.基于cglib的动态代理代码 总结 1.概念 1.AOP技术简介 AOP 为Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP 是 OOP 的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一

  • 深入理解Spring事务原理

    一.事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的.对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:  1.获取连接 Connection con = DriverManager.getConnection()  2.开启事务con.setAutoCommit(true/false);  3.执行CRUD  4.提交事务/回滚事务 con.commit() / con.rollback();  5.关闭连接

  • 简单理解Spring之IOC和AOP及代码示例

    Spring是一个开源框架,主要实现两件事,IOC(控制反转)和AOP(面向切面编程). IOC 控制反转,也可以称为依赖倒置. 所谓依赖,从程序的角度看,就是比如A要调用B的方法,那么A就依赖于B,反正A要用到B,则A依赖于B.所谓倒置,你必须理解如果不倒置,会怎么着,因为A必须要有B,才可以调用B,如果不倒置,意思就是A主动获取B的实例:Bb=newB(),这就是最简单的获取B实例的方法(当然还有各种设计模式可以帮助你去获得B的实例,比如工厂.Locator等等),然后你就可以调用b对象了.

  • Spring框架AOP面向切面编程原理全面分析

    目录 1.什么是AOP AOP面向切面的优势 AOP需要添加的依赖 2.简述AOP工作运行原理 动态创建的总结: 3.使用Spring创建AOP 测试类 Spring.xml 1.什么是AOP AOP:Aspect Oriented Programming ⾯向切⾯编程. AOP面向切面的优势 降低模块之间的耦合度. 使系统更容易扩展. 更好的代码复⽤. ⾮业务代码更加集中,不分散,便于统⼀管理. 业务代码更加简洁存粹,不参杂其他代码的影响. AOP 是对⾯向对象编程的⼀个补充,在运⾏时,动态地

随机推荐