Spring AOP 中的关键概念
Spring AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,旨在通过将横切关注点(如日记纪录、事件管理等)从业务逻辑中分离出来,进步模块化程度。以下是 Spring AOP 中的一些关键概念:
- Aspect(切面)
- 切面是关注点的模块化,比方日记纪录、事件管理等。切面可以包含多个通知(Advice)。
- Join Point(连接点)
- 连接点是指程序执行过程中的某个特定点,如方法调用、异常抛出等。在 Spring AOP 中,连接点总是方法调用。
- Pointcut(切点)
- 切点界说了哪些连接点会被通知所影响。切点通常利用表达式来匹配特定的方法署名。
- Advice(通知)
- 通知是在特定的连接点上执行的代码块。Spring AOP 支持多种类型的通知:
- Before Advice(前置通知):在方法调用之前执行。
- After Returning Advice(后置返回通知):在方法成功返回之后执行。
- After Throwing Advice(后置异常通知):在方法抛出异常之后执行。
- After (finally) Advice(终极通知):无论方法是否抛出异常,都会在方法结束时执行。
- Around Advice(围绕通知):在方法调用之前和之后都执行,可以控制是否继承执行方法。
- Target Object(目标对象)
- Weaving(织入)
- 织入是将切面应用到目标对象的过程。织入可以在编译时、类加载时或运行时进行。
头脑导图
- Spring AOP
- │
- ├── Aspect(切面)
- │ ├── 包含多个通知
- │ └── 关注点的模块化
- │
- ├── Join Point(连接点)
- │ ├── 方法调用
- │ └── 特定的程序执行点
- │
- ├── Pointcut(切点)
- │ ├── 定义哪些连接点会被通知影响
- │ └── 使用表达式匹配方法签名
- │
- ├── Advice(通知)
- │ ├── Before Advice(前置通知)
- │ ├── After Returning Advice(后置返回通知)
- │ ├── After Throwing Advice(后置异常通知)
- │ ├── After (finally) Advice(最终通知)
- │ └── Around Advice(环绕通知)
- │
- ├── Target Object(目标对象)
- │ └── 被通知的对象
- │
- └── Weaving(织入)
- └── 将切面应用到目标对象的过程
复制代码 代码示例
假设我们有一个简单的用户服务接口和实现类,我们将利用 Spring AOP 来添加日记纪录功能。
1. 添加依靠
起首,在 pom.xml 文件中添加 Spring AOP 和 AspectJ 的依靠:
- <dependencies>
- <!-- Spring Core -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>5.3.10</version>
- </dependency>
- <!-- Spring Context -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>5.3.10</version>
- </dependency>
- <!-- Spring AOP -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aop</artifactId>
- <version>5.3.10</version>
- </dependency>
- <!-- AspectJ -->
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjweaver</artifactId>
- <version>1.9.7</version>
- </dependency>
- </dependencies>
复制代码 2. 创建用户服务接口和实现类
接口
- package com.example.service;
- public interface UserService {
- void addUser(String name);
- }
复制代码 实现类
- package com.example.service;
- public class UserServiceImpl implements UserService {
- @Override
- public void addUser(String name) {
- System.out.println("Adding user: " + name);
- }
- }
复制代码 3. 创建切面类
- package com.example.aspect;
- import org.aspectj.lang.annotation.After;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.aspectj.lang.annotation.Pointcut;
- @Aspect
- public class LoggingAspect {
- @Pointcut("execution(* com.example.service.UserServiceImpl.addUser(..))")
- public void addUserPointcut() {}
- @Before("addUserPointcut()")
- public void logBefore() {
- System.out.println("Logging before method execution");
- }
- @After("addUserPointcut()")
- public void logAfter() {
- System.out.println("Logging after method execution");
- }
- }
复制代码 4. 配置 Spring 容器
创建一个 Spring 配置文件 applicationContext.xml,启用 AOP 自动代理并配置切面:
- <?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: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/aop
- http://www.springframework.org/schema/aop/spring-aop.xsd">
- <!-- 启用 AOP 自动代理 -->
- <aop:config>
- <aop:aspect ref="loggingAspect">
- <aop:before method="logBefore" pointcut="execution(* com.example.service.UserServiceImpl.addUser(..))"/>
- <aop:after method="logAfter" pointcut="execution(* com.example.service.UserServiceImpl.addUser(..))"/>
- </aop:aspect>
- </aop:config>
- <!-- 配置切面 -->
- <bean id="loggingAspect" class="com.example.aspect.LoggingAspect"/>
- <!-- 配置目标对象 -->
- <bean id="userService" class="com.example.service.UserServiceImpl"/>
- </beans>
复制代码 5. 测试
创建一个测试类来验证 AOP 是否生效:
- package com.example.test;
- import com.example.service.UserService;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class TestAOP {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- UserService userService = context.getBean(UserService.class);
- userService.addUser("John Doe");
- }
- }
复制代码 运行结果
运行上述测试类,输出应为:
- Logging before method execution
- Adding user: John Doe
- Logging after method execution
复制代码 总结
通过上述示例,我们可以看到 Spring AOP 如何通过切面、连接点、切点和通知来实现横切关注点的模块化。这使得我们的业务逻辑更加清晰,同时保持了高内聚和低耦合。
希望这些信息对你有所资助!假如你有任何其他问题或需要进一步的表明,请随时提问。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |