Spring 全家桶之 Spring Framework 5.3(五)- AOP(二)

简介: Spring 全家桶之 Spring Framework 5.3(五)- AOP

二、AOP

image.png

1. 切面(Aspect)

被抽取出来的公共模块,可以用来会横切多个对象多个方法。Aspect切面可以看成Pointcut切点和Advice通知的结合,一个切面可以由多个切点和通知组成。

2. 连接点(Join point)

指程序运行过程中所执行的方法。在Spring AOP中,一个连接点总代表一个方法的执行。

3. 切点(Pointcut)

切点用于定义要对哪些连接点或者方法的执行前后(Join point)进行拦截。

4. 通知(Advice)

指要在连接点(Join Point) 上执行的动作,即增强的逻辑。比如权限校验和、日志记录,事务控制等。通知有各种类型,包括Around、Before、After、After returning、After throwing

如何使用AOP

首先增加Spring AOP的相关依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>${spring-version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>${spring-version}</version>
</dependency>
复制代码

新增aspect包,增加一个LogAspect切面类,@Component注解表示要将切面类注入到Spring容器中,@Aspect表示这是一个切面类,针对div方法定义了异常通知,对add方法定义了前置通知,后置通知返回通知和环绕通知

@Component
@Aspect
public class LogAspect {
    @Pointcut("execution(public * com.citi.util.impl.AppleCalculator.add(int, int))")
    public void addPointCut(){
    }
    @Pointcut("execution(public * com.citi.util.impl.AppleCalculator.div(int, int))")
    public void divPointCut(){
    }
    @Before("addPointCut()")
    public void logStart(JoinPoint joinPoint ){
        System.out.println("方法调用前的输出");
        System.out.println("方法名:" + joinPoint.getSignature());
        System.out.println("方法参数:" + Arrays.toString(joinPoint.getArgs()));
    }
    @After("addPointCut()")
    public void logEnd(){
        System.out.println("方法调用后的输出");
    }
    @AfterReturning("addPointCut()")
    public void logReturn(){
        System.out.println("方法输出返回后输出");
    }
    @AfterThrowing("divPointCut()")
    public void logException(){
        System.out.println("方法抛出异常后输出");
    }
    @Around("addPointCut()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知:方法执行前");
        Object o = joinPoint.proceed();
        System.out.println("环绕通知:方法执行后输出" + o.toString());
        return o;
    }
}
复制代码

编写测试类,注意注入的是Calculator接口类,不是AppleCalculator实现类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:application.xml")
public class AppleCalculatorTest {
    @Autowired
    private Calculator calculator;
    @Test
    public void add() {
        calculator.add(2,1);
    }
    @Test
    public void div() {
        calculator.div(2,0);
    }
}
复制代码

增加xml配置,开启AOP

<!--开启AOP-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
复制代码

执行测试,div的异常通知可以正常输出,add方法的前置后置返回通知和环绕通知也都可以正常输出

image.png

1.实现接口的情况下使用jdk动态代理创建动态代理对象

执行测试方法

@Test
public void testGetBean(){
    System.out.println(calculator);
    System.out.println(calculator.getClass());
}
复制代码

image.png

从Spring容器中获取目标对象一定要自动导入接口类,不要用本类,AOP底层是动态代理,容器中保存的组件是目标对象的代理对象

如果AppleCalculator不实现接口的情况下,使用cglib创建动态代理,修改AppleCalculator

@Component
public class AppleCalculator {
    public int add(int x, int y) {
        int result = x + y;
        return result;
    }
    public int sub(int x, int y) {
        int result = x - y;
        return result;
    }
    public int mul(int x, int y) {
        int result = x * y;
        return result;
    }
    public int div(int x, int y) {
        int result = x / y;
        return result;
    }
}
复制代码

测试类中注入

@Autowired
private AppleCalculator calculator;
复制代码

执行testGetBean()测试方法,可以看出是CGLIB创建的代理对象

image.png

2.切入点表达式

固定格式: execution(访问权限符  返回值类型  方法全类名(参数表))

通配符:

*:

1)匹配一个或者多个字符:execution(public int com.citi.util.impl.AppleCar.(int, int))

2)匹配任意一个参数:第一个是int类型,第二个参数任意类型;(匹配两个参数) execution(public int com.citi.util.impl.AppleCa*.*(int, *))

3)*只能匹配一层路径

4)权限位置不能使用*,权限位置不写就行或者public(可选)

..

1)匹配任意多个参数,任意类型参数

2)匹配任意多层路径:execution(public int com.citi..AppleCa*.*(..));

记住两种:

最精确的:execution(public int com.citi.util.impl.AppleCalculator.add(int,int))

最模糊的:execution(* .(..)),不要使用这种最模糊的切点表达式

"&&”、“||”、“!"

&&:我们要切入的位置同时满足这两个表达式 execution(public int com.citi.util.impl.AppleCalculator.add(..))&&execution(* .(int,int))

||:满足任意一个表达式即可 execution(public int com.citi..AppleC*.(..))&&execution(.(int,int))

!:只要不是这个位置都切入!execution(public int com.citi..AppleC*.*(..))

3.通知方法的执行顺序

没有环绕通知的情况下,使用try/catch包裹:

try{
    @Before
    // 方法执行
    method.invoke(obj,args);
    // 正常执行后返回
    @AfterReturning
}catch(){
    // 异常执行
    @AfterThrowing
}finally{
    @After
}
复制代码

正常执行:@Before前置通知->@AfterReturning正常返回->@After后置通知

异常执行:@Before前置通知->@After后置通知->@AfterThrowing异常通知


相关文章
|
3月前
|
Java
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
16天前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
1月前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
40 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
21天前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
30 1
|
17天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
31 0
|
2月前
|
设计模式 Java 测试技术
spring复习04,静态代理动态代理,AOP
这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
spring复习04,静态代理动态代理,AOP
|
1月前
|
Java 编译器 Spring
Spring AOP 和 AspectJ 的区别
Spring AOP和AspectJ AOP都是面向切面编程(AOP)的实现,但它们在实现方式、灵活性、依赖性、性能和使用场景等方面存在显著区别。‌
81 2
|
1月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
134 9
|
1月前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
48 0
|
2月前
|
Java 数据库连接 数据库
Spring基础3——AOP,事务管理
AOP简介、入门案例、工作流程、切入点表达式、环绕通知、通知获取参数或返回值或异常、事务管理
Spring基础3——AOP,事务管理
下一篇
无影云桌面