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切面自定代理创建器。


相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
相关文章
|
5天前
|
搜索推荐 JavaScript Java
基于springboot的儿童家长教育能力提升学习系统
本系统聚焦儿童家长教育能力提升,针对家庭教育中理念混乱、时间不足、个性化服务缺失等问题,构建科学、系统、个性化的在线学习平台。融合Spring Boot、Vue等先进技术,整合优质教育资源,提供高效便捷的学习路径,助力家长掌握科学育儿方法,促进儿童全面健康发展,推动家庭和谐与社会进步。
|
1月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
304 0
|
5月前
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
|
2月前
|
人工智能 监控 安全
Spring AOP切面编程颠覆传统!3大核心注解+5种通知类型,让业务代码纯净如初
本文介绍了AOP(面向切面编程)的基本概念、优势及其在Spring Boot中的使用。AOP作为OOP的补充,通过将横切关注点(如日志、安全、事务等)与业务逻辑分离,实现代码解耦,提升模块化程度、可维护性和灵活性。文章详细讲解了Spring AOP的核心概念,包括切面、切点、通知等,并提供了在Spring Boot中实现AOP的具体步骤和代码示例。此外,还列举了AOP在日志记录、性能监控、事务管理和安全控制等场景中的实际应用。通过本文,开发者可以快速掌握AOP编程思想及其实践技巧。
|
2月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
2月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
6月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
410 70
|
4月前
|
安全 Java 数据库
Spring Boot 框架深入学习示例教程详解
本教程深入讲解Spring Boot框架,先介绍其基础概念与优势,如自动配置、独立运行等。通过搭建项目、配置数据库等步骤展示技术方案,并结合RESTful API开发实例帮助学习。内容涵盖环境搭建、核心组件应用(Spring MVC、Spring Data JPA、Spring Security)及示例项目——在线书店系统,助你掌握Spring Boot开发全流程。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
516 2
|
6月前
|
Java Spring
Spring框架的学习与应用
总的来说,Spring框架是Java开发中的一把强大的工具。通过理解其核心概念,通过实践来学习和掌握,你可以充分利用Spring框架的强大功能,提高你的开发效率和代码质量。
153 20