Spring AOP 编程入门

什么是OOP?

 面向对象编程,也称为OOP(即Object Oriented Programming),通过的是继承、封装和多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合,最大的优点在于能够将业务模块进行封装,从而达到功能复用的目的。

什么是AOP?

  面向切面编程,也称为AOP(即Aspect Oriented Programming),指的是将一定的切面逻辑按照一定的方式编织到指定的业务模块中,从而将这些业务模块的调用包裹起来。OOP从纵向上区分出一个个的类来,而AOP则从横向上向对象中加入特定的代码。AOP采用"横切"的技术,解剖开封装的对象内部,将影响了多个类的公共行为封装到一个可重用模块。将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

AOP相关术语 

1.切面(Aspect)

指定了当前切面逻辑所要包裹的业务模块的范围大小,定义了切面的全部内容——它是什么,在何时和何处完成其功能。

2.通知(Advice)

通知定义了切面是什么以及何时使用。除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题。

  • @Before:该注解标注的方法在业务模块代码执行之前执行,其不能阻止业务模块的执行,除非抛出异常;
  • @AfterReturning:该注解标注的方法在业务模块代码执行之后执行;
  • @AfterThrowing:该注解标注的方法在业务模块抛出指定异常后执行;
  • @After:该注解标注的方法在所有的Advice执行完成后执行,无论业务模块是否抛出异常;
  • @Around:该注解功能最为强大,其所标注的方法用于编写包裹业务模块执行的代码,其可以传入一个ProceedingJoinPoint用于调用业务模块的代码,无论是调用前逻辑还是调用后逻辑,都可以在该方法中编写,甚至其可以根据一定的条件而阻断业务模块的调用;
  • @DeclareParents:其是一种Introduction类型的模型,在属性声明上使用,主要用于为指定的业务模块添加新的接口和相应的实现。

3.连接点(Joint point)

是指在程序执行期间的一个点,比如某个方法的执行或者是某个异常的处理。在Spring AOP中,一个连接点往往代表的是一个方法执行

4.切入点(Pointcut)

是指匹配连接点的一个断言。通知是和一个切入点表达式关联的,并且在任何被切入点匹配的连接点上运行(举例,使用特定的名字执行某个方法)。AOP的核心就是切入点表达式匹配连接点的思想。

切点表达式

  1. execution:Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的,execution表达式的语法:
  •  
    execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
  • modifiers-pattern:方法的可见性,如public,protected;
  • ret-type-pattern:方法的返回值类型,如int,void等;
  • declaring-type-pattern:方法所在类的全路径名,如com.example.demo.controller;
  • name-pattern:方法名类型,如EatWMZ();
  • param-pattern:方法的参数类型,如java.lang.String;
  • throws-pattern:方法抛出的异常类型,如java.lang.Exception;

如:

execution(public * com.example.demo.controller.AopController.*(..)))

   2.within:within表达式的粒度为类,其参数为全路径的类名(可使用通配符),表示匹配当前表达式的所有类都将被当前方法环绕。

如:

within( com.example.demo.controller.AopController)

 表示匹配com.example.demo.controller.AopController 下的所有方法


5.引入(Introduction)

代表了对一个类型额外的方法或者属性的声明。Spring AOP允许引入新接口到任何被通知对象(以及一个对应实现)。比如,可以使用一个引入去使一个bean实现IsModified接口,从而简化缓存机制。(在AspectJ社区中,一个引入也称为一个inter-type declaration类型间声明)

6.目标对象(Target object)

是指被一个或多个切面通知的那个对象。也指被通知对象("advised object"),由于Spring AOP是通过运行时代理事项的,这个目标对象往往是一个代理对象

7.AOP 代理(AOP proxy)

是指通过AOP框架创建的对象,用来实现切面合约的(执行通知方法等等)。在Spring框架中,一个AOP代理是一个JDK动态代理或者是一个CGLIB代理

8.织入(Weaving)

将切面和其他应用类型或者对象连接起来,创建一个被通知对象。这些可以在编译时(如使用AspectJ编译器)、加载时或者运行时完成。Spring AOP,比如其他纯Java AOP框架一般是在运行时完成织入。

SpringBoot中集成AOP

1.pom.xml引入

maven依赖添加如下
<!--引入SpringBoot的Web模块-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
 
<!--引入AOP依赖-->
   <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
   </dependency>

 2.定义切面类

@Aspect 注解 使之成为切面类

@Component 注解 把切面类加入到IOC容器中

package com.example.demo.aop;

import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 饿鸟嘛配送
 **/
@Aspect
@Component
public class EatAop {

    /**
    *@description 定义切入点,切入点为com.example.demo.controller.AopController中的所有函数
    *@description 通过@Pointcut注解声明频繁使用的切点表达式
    * */
    @Pointcut("execution(public * com.example.demo.controller.AopController.*(..)))")
    public void EatAop()
    {

    }
    /**
     * @description  在连接点执行之前执行的通知
     */
    @Before("EatAop()")
    public void doBeforeEat(){
        System.out.println("饿鸟嘛配送员登录接单系统为接单做准备!");
    }

    /**
     * @description  在连接点执行之后执行的通知(返回通知和异常通知的异常)
     */
    @After("EatAop()")
    public void doAfterEat(){
        System.out.println("饿鸟嘛配送员为今天的外卖单量感到异常吃惊!");
    }

    /**
     * @description  在连接点执行之后执行的通知(返回通知)
     */
    @AfterReturning("EatAop()")
    public void doAfterReturningEat(){
        System.out.println("返回的通知:饿鸟嘛配送员接单完毕,并会心一笑百媚生!");
    }

    /**
     * @description  在连接点执行之后执行的通知(异常通知)
     */
    @AfterThrowing("EatAop()")
    public void doAfterThrowingGame(){
        System.out.println("异常通知:服务错误,请联系饿鸟嘛系统管理员!");
    }

}

3.新建AopController

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class AopController {

    @RequestMapping(value = "/EatWMZ")
    public void EatWMZ(){
        System.out.println("王麻子点了一份瓜皮香锅");
    }
    @RequestMapping(value = "/EatZS")
    public void EatZS(){
        System.out.println("张三点了一份爆浆牛丸");
    }
}

访问http://127.0.0.1:8080/api/EatWMZ

小结

   本文首先对AOP进行了简单介绍,然后介绍了切面中的相关术语,举例说明切点表达式其中常用的两种,最后做了简单的demo旨在说明切面逻辑(advice)下各个类型执行的顺序。

猜你喜欢

转载自blog.csdn.net/qq_27462223/article/details/106807143