Spring中的AOP操作你了解吗

目录
  • 一、AOP操作术语
    • 1. 连接点
    • 2. 切入点
    • 3. 通知(增强)
    • 4. 切面
  • 二、AOP操作
    • 2.1 切入点表达式
    • 2.2 AOP操作(AspectJ 注解方式)
    • 2.3 相同切入点的抽取
    • 2.4 多个增强类对同一个方法进行增强,设置增强类优先级
  • 三、结束

一、AOP操作术语

1. 连接点

类里面哪些方法可以被增强,这些可以被增强的方法就称为连接点。

2. 切入点

实际被真正增强的方法,称为切入点。

3. 通知(增强)

(1)实际增强的逻辑部分称为通知(增强)

(2)通知有如下多种类型,如下:

  • 前置通知
  • 后置通知
  • 环绕通知
  • 异常通知
  • 最终通知(finally)

4. 切面

切面是一个动作,指的是将通知应用到切入点的过程,就叫做切面。

二、AOP操作

Spring 框架一般都是基于 AspectJ 实现 AOP 操作。AspectJ 不是 Spring 组成部分,而是独立 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使用,进行 AOP 操作 。

基于AspectJ实现AOP操作有如下两种方式:

  • 基于 xml 配置文件实现
  • 基于注解方式实现(使用)

2.1 切入点表达式

切入点表达式作用:知道对哪个类里面的哪个方法进行增强 ,语法结构如下所示:

execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) 

如下图所示: 

编写切点示例如下

1. 如对com.wyf.spring5.Book类中的add进行增强,则切入点表达式如下:

execution(* com.wyf.spring5.Book.add(..))

2. 如对com.wyf.spring5.Book类中所有的方法增强:

execution(* com.wyf.spring5.Book.*(..))

3. 如对 com.wyf.spring5包中的所有类,类中的所有方法都进行加强

execution(*  com.wyf.spring5.*.* (..)) 

2.2 AOP操作(AspectJ 注解方式)

 1) 首先我们创建一个类,并添加一个方法

/** * 被增强类 */public class User {    public void add(){        System.out.println("add*****");    }}/**
 * 被增强类
 */
public class User {
    public void add(){
        System.out.println("add*****");
    }
}

2)接着我们创建增强类(编写增强逻辑)

在增强类中创建方法,让不同的方法代表不同的通知类型

/**
 * 增强类
 */
public class UserProxy {
    /**
     * 前置通知逻辑
     */
    public void before(){
        System.out.println("before*****");
    }
}

3)进行通知的配置

在spring配置文件中,开启注解扫描。(采用java配置类或xml配置文件实现)

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:aop="http://www.springframework.org/schema/aop"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">    <!-- 开启注解扫描 -->    <context:component-scan base-package="com.wyf.aopanno"></context:component-scan>    <!-- 开启Aspect 生成代理对象 -->    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>    </beans><?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- 开启注解扫描 -->
    <context:component-scan base-package="com.wyf.aopanno"></context:component-scan>
    <!-- 开启Aspect 生成代理对象 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
  • 使用注解创建User和UserProxy对象(类上面添加创建对象注解,此处为 @Component)
  • 在增强类上面添加注解@Aspect
/**
 * 被增强类
 */
@Component
public class User {
    public void add(){
        System.out.println("add*****");
    }
}
/**
 * 增强类
 */
@Component
@Aspect  //生成代理对象
public class UserProxy {
    /**
     * 前置通知逻辑
     */
    public void before(){
        System.out.println("before*****");
    }
}

在 spring 配置文件中开启生成代理对象 

    <!-- 开启Aspect 生成代理对象 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

开启Aspect生成代理对象,相当扫描带有@Aspect注解的类,并生成该对象的一个代理对象。

4)配置不同类型通知

在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置。

/**
 * 增强类
 */
@Component
@Aspect  //生成代理对象
public class UserProxy {
    /**
     * 前置通知逻辑
     */
    //@Before注解表示其作为前置通知
    //切入点表达式指定该通知为哪个类的哪个方法进行增强。
    @Before(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void before(){
        System.out.println("before*****");
    }
}

测试代码如下:

    @Test
    public void TestAop(){
        //1. 加载spring 配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("beanAop1.xml");
        //得到对象
        User user = context.getBean("user",User.class);
        user.add();
    }

执行结果:

前文只给出了前置通知@Before的代码,下面给出所有5种通知的示例代码,对上例的所有通知情况进行补全。

/**
 * 增强类
 */
@Component
@Aspect  //生成代理对象
public class UserProxy {
    /**
     * 前置通知逻辑
     */
    //@Before注解表示其作为前置通知
    //切入点表达式指定该通知为哪个类的哪个方法进行增强。
    @Before(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void before(){
        System.out.println("before*****");
    }
    /**
     * 后置通知(返回通知)
     */
    @AfterReturning(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning*****");
    }
    /**
     * 最终通知,有异常也会执行
     */
    @After(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void after(){
        System.out.println("after*****");
    }
    /**
     * 异常通知
     */
    @AfterThrowing(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void afterthrowing(){
        System.out.println("afterthrowing*****");
    }
    /**
     * 环绕通知,在方法之前和之后均通知
     */
    @Around(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕之前*****");
        //执行被增强的方法
        proceedingJoinPoint.proceed();
        System.out.println("环绕之后*****");
    }

代码执行结果如下:

其中,after是在被增强方法之后执行,而afterreturning是在方法返回值之后执行。

2.3 相同切入点的抽取

在上例种,我们编写了被增强方放的5种通知,分别为前置通知、后置通知、异常通知、最终通知以及环绕通知。我们在编写增强类时,在通知注解中通过切入点表达式,指明了通知要对哪个类的哪个方法进行增强。但是,我们会发现,我们对同一方法进行增强时,其切入点表达式是相同的,为了避免重复,我们可以相同切入点进行抽取。

下例中,我们将相同切入点用@Pointcut进行了抽取,代码如下所示:

    //对相同切入点进行抽取
    @Pointcut(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void pointdemo(){
    }

当我们在其他地方要用该切入点表达式时,直接用其方法名称就可以。

如下所示:

@Component
@Aspect
@Order(2)
public class PersonProxy {
    //前置通知
    @Before(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void before(){
        System.out.println("Person Before****");
    }
}

2.4 多个增强类对同一个方法进行增强,设置增强类优先级

假如我们现在又有一个增强类,其中也包含一个before()方法,也对被增强类User的add()方法进行前置增强。那么我们如何设置其增强的顺序呢?

我们通过在增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高 ,来保证增强的顺寻,代码如下:

@Component
@Aspect
@Order(2)
public class PersonProxy {
    //前置通知
    @Before(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void before(){
        System.out.println("Person Before****");
    }
}

三、结束

本文主要介绍了AOP关键子以及基于注解的AOP操作,通过一个实例,介绍了AOP的前置通知、后置通知、异常通知、最终通知以及环绕通知。

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Spring-AOP 静态普通方法名匹配切面操作

    概述 StaticMethodMatcherPointcutAdvisor代表一个静态方法匹配切面,它通过StaticMethodMatcherPointcut来定义切点,并通过类过滤和方法名来匹配所定义的切点. 实例 代码已托管到Github-> https://github.com/yangshangwei/SpringMaster 我们假设我们业务类中 Waiter和 Seller中都有同名的greetTo()方法. 业务类Waiter package com.xgj.aop.spring

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

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

  • SpringAOP实现登录验证的操作代码

    要求任何操作都建立在已经登录的基础上,登录操作除外.... 使用Spring AOP不仅简单,还不会对其他部件中产生影响 以下具体代码实现: package com.joey.util; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ann

  • Spring AOP访问目标方法的参数操作示例

    本文实例讲述了Spring AOP访问目标方法的参数操作.分享给大家供大家参考,具体如下: 一 配置 <?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns

  • SpringAop实现操作日志记录

    前言 大家好,这里是经典鸡翅,今天给大家带来一篇基于SpringAop实现的操作日志记录的解决的方案.大家可能会说,切,操作日志记录这么简单的东西,老生常谈了.不! 网上的操作日志一般就是记录操作人,操作的描述,ip等.好一点的增加了修改的数据和执行时间.那么!我这篇有什么不同呢!今天这种不仅可以记录上方所说的一切,还增加记录了操作前的数据,错误的信息,堆栈信息等.正文开始~~~~~ 思路介绍 记录操作日志的操作前数据是需要思考的重点.我们以修改场景来作为探讨.当我们要完全记录数据的流向的时候,

  • spring-AOP 及 AOP获取request各项参数操作

    spring-AOP 及 AOP获取request各项参数 AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待. 一.AOP的基本概念 Aspect(切面):通常是一个类,里面可以定义切入点和通知 JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用 Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around Pointcut(切入点

  • Spring中的AOP操作你了解吗

    目录 一.AOP操作术语 1. 连接点 2. 切入点 3. 通知(增强) 4. 切面 二.AOP操作 2.1 切入点表达式 2.2 AOP操作(AspectJ 注解方式) 2.3 相同切入点的抽取 2.4 多个增强类对同一个方法进行增强,设置增强类优先级 三.结束 一.AOP操作术语 1. 连接点 类里面哪些方法可以被增强,这些可以被增强的方法就称为连接点. 2. 切入点 实际被真正增强的方法,称为切入点. 3. 通知(增强) (1)实际增强的逻辑部分称为通知(增强) (2)通知有如下多种类型,

  • 一篇文章从无到有详解Spring中的AOP

    前言 AOP (Aspect Orient Programming),直译过来就是 面向切面编程.AOP 是一种编程思想,是面向对象编程(OOP)的一种补充.面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面. 从<Spring实战(第4版)>图书中扒了一张图: 从该图可以很形象地看出,所谓切面,相当于应用对象间的横切点,我们可以将其单独抽象为单独的模块. <?xml version="1.0" encoding="UTF-8&qu

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

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

  • 详解在spring中使用JdbcTemplate操作数据库的几种方式

    使用JdbcTemplate的步骤 1.设置spring-jdbc和spring-tx的坐标(也就是导入依赖) <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.7.RELEASE</version> </dependency> <dependency&

  • Spring中的事务操作、注解及XML配置详解

    事务 事务全称叫数据库事务,是数据库并发控制时的基本单位,它是一个操作集合,这些操作要么不执行,要么都执行,不可分割.例如我们的转账这个业务,就需要进行数据库事务的处理. 转账中至少会涉及到两条 SQL 语句: update Acoount set balance = balance - money where id = 'A'; update Acoount set balance = balance + money where id = 'B' 上面这两条 SQL 就可以要看成是一个事务,必

  • Spring中IOC和AOP的深入讲解

    前言 Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来.它是为了解决企业应用开发的复杂性而创建的.Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spring的用途不仅限于服务器端的开发.从简单性.可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益

  • 浅谈一下Spring中的createBean

    目录 找到BeanClass并且加载类 实例化前 实例化 Supplier创建对象 工厂方法创建对象 推断构造方法 BeanDefionition 的后置处理 实例化后 属性填充 Aware回调 初始化前 初始化 初始化后 总结BeanPostProcessor 找到BeanClass并且加载类 protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws

  • 在Spring中使用JDBC和JDBC模板的讲解

    spring dao层中对jdbc进行了封装,使用模板模式的设计模式,通过ioc被动注入的方式将jdbcTemplate这个模板类注入到数据对象中,进行数据库操作. 我们要在一个类中进行CRUD操作(crud主要被用在描述软件系统中数据库或者持久层的基本操作功能.),首先要将jdbcTemplate这个模板类注入到数据对象类中,然后将DataSource这个类注入到jdbcTemplate,获取数据源. 这样数据对象类就可以通过jdbcTemplate类中的方法进行数据库操作了. 注意:这里需要

  • 解析Spring中面向切面编程

    一.AOP--另一种编程思想 1.1.什么是 AOP AOP (Aspect Orient Programming),直译过来就是 面向切面编程.AOP 是一种编程思想,是面向对象编程(OOP)的一种补充.面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面. 从<Spring实战(第4版)>图书中扒了一张图: 从该图可以很形象地看出,所谓切面,相当于应用对象间的横切点,我们可以将其单独抽象为单独的模块. 1.2.为什么需要 AOP 想象下面的场景,开发中在多个模块间有

  • 详解Spring中Bean的作用域与生命周期

    目录 一.Bean的作用域 二.Bean的生命周期 使用代码演示Bean的生命周期 一.Bean的作用域 通过Spring容器创建一个Bean的实例时,不仅可以完成Bean的实例化,还可以使用Bean的scope属性为bean设置作用域. 语法格式:<bean id="别名" scope="作用域" class="对应实现类"> 作用域的种类:(sing) singleton和prototype区别:(该两种比较常用) ① singl

随机推荐