Springboot中切面编程AOP是怎样的

发布时间:2021-09-29 17:06:28 作者:柒染
来源:亿速云 阅读:174
# Spring Boot中切面编程AOP是怎样的

## 目录
1. [AOP核心概念解析](#1-aop核心概念解析)  
2. [Spring AOP实现原理](#2-spring-aop实现原理)  
3. [Spring Boot中的AOP配置](#3-spring-boot中的aop配置)  
4. [五种通知类型详解](#4-五种通知类型详解)  
5. [切点表达式语法](#5-切点表达式语法)  
6. [AOP最佳实践](#6-aop最佳实践)  
7. [性能优化与常见问题](#7-性能优化与常见问题)  
8. [与AspectJ对比](#8-与aspectj对比)  

---

## 1. AOP核心概念解析

### 1.1 什么是AOP
面向切面编程(Aspect-Oriented Programming)是一种通过预编译方式和运行时动态代理实现程序功能统一维护的技术。在Spring Boot中,AOP主要用于实现横切关注点(如日志、事务、安全等)与业务逻辑的分离。

```java
// 典型AOP应用场景示例
@Transactional
public void transferMoney(Account from, Account to, double amount) {
    // 业务逻辑代码
}

1.2 AOP核心术语

术语 说明
Aspect(切面) 横切关注点的模块化实现(如日志模块)
JoinPoint 程序执行过程中的特定点(如方法调用)
Advice 在特定JoinPoint执行的动作
Pointcut 匹配JoinPoint的谓词表达式
Target 被代理的原始对象
Weaving 将切面应用到目标对象创建代理的过程

2. Spring AOP实现原理

2.1 代理模式实现

Spring AOP默认使用动态代理技术: - JDK动态代理:基于接口实现(要求目标类必须实现接口) - CGLIB代理:通过子类化实现(可代理普通类)

// JDK代理示例
public class JdkProxyDemo {
    public static void main(String[] args) {
        UserService target = new UserServiceImpl();
        UserService proxy = (UserService) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            (p, method, params) -> {
                System.out.println("Before method: " + method.getName());
                return method.invoke(target, params);
            });
        proxy.saveUser();
    }
}

2.2 代理创建流程

  1. 解析所有切面定义
  2. 创建目标对象Bean
  3. 根据条件选择代理方式
  4. 生成代理对象并注入容器

3. Spring Boot中的AOP配置

3.1 自动配置原理

Spring Boot通过spring-boot-starter-aop自动配置:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

自动配置类AopAutoConfiguration关键逻辑:

@Configuration
@ConditionalOnClass(EnableAspectJAutoProxy.class)
public class AopAutoConfiguration {
    @Configuration
    @EnableAspectJAutoProxy(proxyTargetClass=false)
    @ConditionalOnProperty(name="spring.aop.auto")
    public static class AspectJAutoProxyingConfiguration {}
}

3.2 自定义配置项

# application.properties
spring.aop.auto=true  # 是否启用AOP自动代理
spring.aop.proxy-target-class=false # 是否强制使用CGLIB

4. 五种通知类型详解

4.1 通知类型对比

通知类型 执行时机 注解
Before 目标方法执行前 @Before
AfterReturning 方法正常返回后 @AfterReturning
AfterThrowing 方法抛出异常时 @AfterThrowing
After 方法执行完成后(无论结果) @After
Around 包围目标方法执行 @Around

4.2 Around通知示例

@Around("execution(* com.example.service.*.*(..))")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
    long start = System.currentTimeMillis();
    Object result = joinPoint.proceed();
    long duration = System.currentTimeMillis() - start;
    logger.info("Method {} executed in {} ms", 
        joinPoint.getSignature(), duration);
    return result;
}

5. 切点表达式语法

5.1 表达式设计器

Spring提供AspectJExpressionPointcut类支持多种匹配方式:

@Pointcut("within(@org.springframework.stereotype.Repository *)")
public void repositoryMethods() {}

@Pointcut("execution(public * *(..))")
public void publicMethod() {}

@Pointcut("repositoryMethods() && publicMethod()")
public void repositoryPublicMethods() {}

5.2 常用表达式模式


6. AOP最佳实践

6.1 事务管理整合

@Aspect
@Component
public class TransactionAspect {
    
    @Autowired
    private PlatformTransactionManager transactionManager;

    @Around("@annotation(transactional)")
    public Object manageTransaction(ProceedingJoinPoint pjp, 
                                   Transactional transactional) throws Throwable {
        TransactionStatus status = transactionManager.getTransaction(
            new DefaultTransactionDefinition(
                transactional.propagation(),
                transactional.isolation()));
        try {
            Object result = pjp.proceed();
            transactionManager.commit(status);
            return result;
        } catch (Exception ex) {
            transactionManager.rollback(status);
            throw ex;
        }
    }
}

6.2 性能监控方案

@Aspect
@Component
public class PerformanceMonitorAspect {
    
    @Around("execution(* com..service.*.*(..))")
    public Object monitorPerformance(ProceedingJoinPoint pjp) throws Throwable {
        String signature = pjp.getSignature().toShortString();
        StopWatch stopWatch = new StopWatch(signature);
        stopWatch.start();
        try {
            return pjp.proceed();
        } finally {
            stopWatch.stop();
            if (stopWatch.getTotalTimeMillis() > 1000) {
                logger.warn("Performance alert: {}", stopWatch.prettyPrint());
            }
        }
    }
}

7. 性能优化与常见问题

7.1 性能优化建议

  1. 精确限定切点表达式范围
  2. 避免在Around通知中做耗时操作
  3. 对高频调用方法禁用AOP
  4. 合理选择代理模式(JDK/CGLIB)

7.2 常见问题排查

问题1:AOP不生效 - 检查是否启用@EnableAspectJAutoProxy - 确认切面类被Spring管理(@Component) - 验证切点表达式是否正确匹配

问题2:循环依赖

// 解决方案:使用@Lazy延迟初始化
@Autowired @Lazy
private OrderService orderService;

8. 与AspectJ对比

8.1 功能对比

特性 Spring AOP AspectJ
织入时机 运行时 编译期/类加载期
性能 中等
功能完整性 部分支持 完整支持
学习曲线 平缓 陡峭
依赖 仅需Spring 需特殊编译器

8.2 适用场景选择


本文完整代码示例可在GitHub仓库获取。实际应用时请根据具体Spring Boot版本调整配置细节,建议结合Spring官方文档进行深入理解。 “`

注:此为精简版大纲,完整10500字文章需扩展以下内容: 1. 每个章节添加详细实现案例 2. 增加性能测试数据对比 3. 补充Spring Boot 3.x新特性 4. 添加异常处理最佳实践 5. 整合Micrometer监控指标 6. 多数据源事务处理方案 7. 完整项目结构示例 8. 各版本兼容性说明

推荐阅读:
  1. SpringBoot2.0 基础案例(11):配置AOP切面编程,解决日志记录业务
  2. 面向切面编程(AOP模式)

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

springboot

上一篇:如何实现ECHO不换行

下一篇:linux shell自定义函数方法有哪些

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》