Spring Framework 源码学习笔记(七)- AOP(上)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Spring Framework 源码学习笔记(七)- AOP

Chapter 07 Spring AOP 基操及源码

Section 01 - AOP基操

新建一个Spring Boot项目spring-aop,添加AOP 相关的依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
复制代码

新建controller包,增加一个HelloController类

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello(){
        return "Hello AOP";
    }
}
复制代码

新建一个config包,首先新增一个BeanConfig,将所有的Bean注册到容器中

@Configuration
@ComponentScan(value = {"com.citi"})
public class BeanConfig {
}
复制代码

再新建一个aop包,增加一个LogAspects类,代码如下

@Component
@Aspect
public class LogAspects {
    @Pointcut("execution(public * com.citi.controller.*.*(..))")
    public void pointCut(){
    }
    @Before("pointCut()")
    public void logStart(){
        System.out.println("方法调用前的输出");
    }
    @After("pointCut()")
    public void logEnd(){
        System.out.println("方法调用后的输出");
    }
    @AfterReturning("pointCut()")
    public void logReturn(){
        System.out.println("方法输出返回后输出");
    }
    @AfterThrowing("pointCut()")
    public void logException(){
        System.out.println("方法抛出异常后输出");
    }
    @Around("pointCut()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知:方法执行前");
        Object o = joinPoint.proceed();
        System.out.println("环绕通知:方法执行后");
        return o;
    }
}
复制代码
通知方法,方法名可以自定义,注解不可以省略
* 前置通知:logStart(),注解@Before
* 后置通知:logEnd(),@After
* 返回通知:logReturn(),方法正常返回后运行, @AfterReturing
* 异常通知:logException(),在方法出现异常后运行, @AfterThrowing
* 环绕通知:动态代理,手动执行joinPoint.porceed()(其实就是执行目标方法), @Around
复制代码

pointCut()是切点表达式方法,表明要针对哪些方法进行切面,即方法执行前后输出日志

* 切入点表达式,针对具体方法的
* public String com.citi.controller.HelloController.hello(int x, int y)
* 针对具体方法(重载方法)的,包含不同的入参,用..表示不同数量的入参
* public String com.citi.controller.HelloController.hello(..)
* 针对某个类下的所有函数,用*代替String
* public * com.citi.controller.HelloController.*.(..)
* 针对某个包下的所有函数的所有方法,每个方法的返回值不同,
* public * com.citi.controller.*.*(..)
复制代码

执行项目的Main方法,项目默认在8080端口,浏览器打开localhost:8080/hello,浏览器输出Hello AOP

188c5b8ffeff437caf161616298e16e0_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

查看控制台打印,方法执行前后都会有日志输出

50d26871a930454aa27f2ada36b80620_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

AOP即面向切面编程,底层就是动态代理,指程序在运行期间动态的将某段代码切入到指定方法位置进行运行的编程方式

模拟异常情况修改HelloController,增加异常3/0

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello(){
        int result = 3 / 0;
        return "Hello AOP";
    }
}
复制代码

重启Main方法,打开浏览器输入localhost:8080/hello,查看控制台日志

7a7075ac3d0246a38a8cae1de26c00fb_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

输出了异常通知

如何输入切面相关的信息,即针对的方法的信息,如方法名,入参等 查看JoinPoint接口源码

c2d12921b03244908def85b5c84d3013_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

可以通过getArgs,getSignature等方法获取相关信息

修改LogAspects类,增加JoinPoint入参,以logBefore()为例

@Before("pointCut()")
public void logStart(JoinPoint joinPoint ){
    System.out.println("方法名:" + joinPoint.getSignature());
    System.out.println("方法参数" + joinPoint.getArgs());
    System.out.println("方法调用前的输出");
}
复制代码

重启应用,打开浏览器输入localhost:8080/hello,查看控制台日志

8dcb13606b6b48f38af3c8e14bd3b6f8_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

输出了切面的相关信息

Section 02 - AOP 源码

SpringBoot默认开启了AOP配置,所以并不需要在BeanConfig配置类上添加@EnableAspectJAutoProxy,但它是开启AOP的核心,查看该注解源码发现使用@Import注解导入了AspectJAutoProxyRegistrar

@Import(AspectJAutoProxyRegistrar.class)
复制代码

查看AspectJAutoProxyRegistrar源码,该类实现了ImportBeanDefinitionRegistrar接口及registerBeanDefinitions方法,该接口的作用是给容器中自定义注册组件,在IoC容器的测试代码中的CustImportBeanDefinitionRegistrar就是实现了该类,并实现了根据条件往容器中注入Bean的功能,如果容器中存在Product和Category才往容器中注入Order。在registerBeanDefinitions打断点Debug

3228bcdea5014e9c809635da9fdcf9ed_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

可以看出一开始registry中有10个Bean,经过下面的代码之后

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
复制代码

registry中多了一个Bean

a8d08e2aa2da45909ffef090e3951156_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

Bean Name为"org.springframework.aop.config.internalAutoProxyCreator" 类型为AnnotationAwareAspectJAutoProxyCreator即注解装配模式的Aspect切面自定代理创建器。


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
16天前
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
79 25
|
16天前
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
69 24
|
1月前
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
|
1月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
1月前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
83 8
|
2月前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
74 2
|
3月前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
111 5
|
3月前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
62 5
|
3月前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
3月前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
72 4