【Java教程】Day22-11 Spring框架:使用AOP——理解与实现面向切面编程

1. 什么是AOP?

AOP(Aspect-Oriented Programming,面向切面编程)是一种不同于传统面向对象编程(OOP)的编程方式。AOP的核心思想是通过将横跨多个业务逻辑的功能(如日志、事务、权限检查等)提取为切面(Aspect),从而使得核心业务逻辑更加简洁与专注。

AOP 与 OOP 的区别

  • OOP:将系统视为由多个对象进行交互和协作,每个对象拥有自己的状态和行为。

  • AOP:将系统分解为多个“切面”,即系统中的关注点,核心逻辑与切面逻辑分开处理。

 

举个例子:在一个 BookService 中,我们有多个业务方法,例如 createBookupdateBook 和 deleteBook。每个方法在执行前都需要进行安全检查、日志记录和事务处理。传统的OOP方式会将这些功能代码写在每个方法中,导致代码重复且不易维护。

AOP的出现帮助我们将这些横切关注点(如安全、日志、事务)抽离出来,避免重复代码,并且可以在不修改业务代码的情况下增强功能。

 

 


2. AOP 的基本术语

在AOP编程中,我们经常会遇到以下概念:

  • Aspect(切面):横跨多个核心逻辑的功能,系统中的一个关注点(例如,日志、事务、安全检查)。

  • Joinpoint(连接点):应用程序流程中可以插入切面代码的点。

  • Pointcut(切入点):一个连接点的集合,可以定义在哪些方法上执行切面代码。

  • Advice(增强):在连接点执行的具体动作,可以是前置增强、后置增强等。

  • Introduction(引介):为已有的Java对象动态增加新的接口。

  • Weaving(织入):将切面与目标对象的代码结合,在程序执行流程中动态应用切面。

  • Interceptor(拦截器):执行增强操作的具体方式。

  • Target Object(目标对象):核心业务逻辑的对象,通常是需要被增强的类。

  • AOP Proxy(AOP代理):客户端持有的、增强后的对象引用。

 

这些术语可能让你对AOP产生疑惑,但实际上,AOP本质上就是一种代理模式,在Spring容器中实现AOP非常简单。


3. AOP 的实现方式

AOP的目标是将切面逻辑与业务逻辑分离,Spring框架通过CGLIB和JDK动态代理来实现AOP。Spring支持通过注解和XML配置两种方式来实现AOP。我们将以Spring AOP为例,了解如何通过注解实现AOP。


4. Spring AOP 使用示例

假设我们有两个核心服务:UserService 和 MailService,并且需要为这些服务的业务方法添加日志功能。具体步骤如下:

4.1 引入Spring AOP依赖

首先,我们通过Maven引入Spring对AOP的支持:


 
xml<dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-aspects</artifactId>    <version>6.0.0</version></dependency>

 

4.2 定义切面类(LoggingAspect)


 

 

java@Aspect@Componentpublic class LoggingAspect {    // 在执行UserService的每个方法前执行:    @Before("execution(public * com.itranswarp.learnjava.service.UserService.*(..))")    public void doAccessCheck() {        System.err.println("[Before] do access check...");    }    // 在执行MailService的每个方法前后执行:    @Around("execution(public * com.itranswarp.learnjava.service.MailService.*(..))")    public Object doLogging(ProceedingJoinPoint pjp) throws Throwable {        System.err.println("[Around] start " + pjp.getSignature());        Object retVal = pjp.proceed();        System.err.println("[Around] done " + pjp.getSignature());        return retVal;    }}

 

4.3 配置Spring AOP

在Spring配置类中,启用AOP支持:


 
java@Configuration@ComponentScan@EnableAspectJAutoProxypublic class AppConfig {    // Spring配置}

 

4.4 执行结果

当我们运行应用程序时,AOP会在指定方法前后自动执行我们定义的增强操作。示例输出如下:


 
csharp[Before] do access check...[Around] start void com.itranswarp.learnjava.service.MailService.sendRegistrationMail(User)Welcome, test![Around] done void com.itranswarp.learnjava.service.MailService.sendRegistrationMail(User)[Before] do access check...[Around] start void com.itranswarp.learnjava.service.MailService.sendLoginMail(User)Hi, Bob! You are logged in at 2020-02-14T23:13:52.167996+08:00[Asia/Shanghai][Around] done void com.itranswarp.learnjava.service.MailService.sendLoginMail(User)

 


5. Spring AOP的代理模式

AOP的工作原理非常简单:Spring容器会自动为我们创建代理类。例如,LoggingAspect.doAccessCheck() 会被自动注入到 UserService 的每个方法执行之前。这一过程背后,Spring通过代理模式创建了一个增强后的 UserService 子类。具体过程如下:


 
javapublic class UserServiceAopProxy extends UserService {    private UserService target;    private LoggingAspect aspect;    public UserServiceAopProxy(UserService target, LoggingAspect aspect) {        this.target = target;        this.aspect = aspect;    }    public User login(String email, String password) {        aspect.doAccessCheck();        return target.login(email, password);    }    public User register(String email, String password, String name) {        aspect.doAccessCheck();        return target.register(email, password, name);    }}

 

通过这种方式,Spring容器自动为 UserService 创建了代理对象,并将切面方法(如 LoggingAspect)注入到代理对象中。


6. AOP的拦截器类型

在Spring AOP中,常见的拦截器类型如下:

  • @Before:在目标方法执行前执行。

  • @After:在目标方法执行后执行,无论目标方法是否抛出异常。

  • @AfterReturning:仅在目标方法正常返回时执行。

  • @AfterThrowing:仅在目标方法抛出异常时执行。

  • @Around:完全控制目标方法的执行,可以在执行前后、异常抛出后执行任意拦截代码。


7. 小结

Spring AOP提供了一种简洁的方式来增强应用程序的功能,特别适用于日志记录、权限检查和事务管理等横切关注点。通过使用注解和动态代理,Spring简化了AOP的实现,让开发者不必关心复杂的代理实现,专注于业务逻辑。

使用Spring AOP的步骤非常简单:

  1. 定义切面(Aspect),并用注解标明要在何处执行。

  2. 在切面类上使用 @Aspect 和 @Component 注解。

  3. 在Spring配置类中启用 @EnableAspectJAutoProxy

 

这样,我们就能轻松实现面向切面编程,从而使我们的业务代码更加清晰、简洁,且易于维护。

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值