You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3.4.x重启后Aspect未触发(3.3.10正常)

Spring Boot 3.4.0 下多租户切面偶尔未触发问题

问题现象

基于Spring Boot 3.4.0开发的应用中,TenantServiceAspect切面用于拦截Repository方法调用,通过Hibernate过滤器实现多租户过滤。该切面在Spring Boot 3.3.10中运行正常,但偶尔在高负载下重启应用后,部分Repository方法(如findByCode)的beforeExecution()方法不会触发。经排查,问题根源是重启时请求在Spring Boot未完全就绪时到达导致。

环境信息

  • Spring Boot版本:3.4.0
  • Java版本:21

相关代码

Batch Rest服务

@RestController
@RequiredArgsConstructor
@RequestMapping("batch")
public class BatchService {
    private final BatchBusinessService batchBusinessService;

    @GetMapping(value = "/findBatchByCode", produces = {MediaType.APPLICATION_JSON_VALUE})
    ResponseEntity<ServiceResponse<BatchDto>> findBatchByCode(@RequestParam("code") String code) {
        return buildResponseEntity(batchBusinessService.findBatchByCode(code));
    };
}

BatchBusinessService类

package com.example.batch.service;

import com.example.batch.data.domain.Batch;
import com.example.batch.data.dto.BatchDto;
import com.example.batch.data.repository.BatchRepository;
import com.example.batch.mapper.BatchMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class BatchBusinessService {
    private final BatchRepository batchRepository;
    private final BatchMapper mapper;

    public BatchDto findBatchByCode(String code) {
        Batch batch = batchRepository.findByCode(code).orElse(null);
        return mapper.toDto(batch);
    }
}

BatchRepository接口

package com.example.batch.data.repository;

import com.example.batch.data.domain.Batch;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface BatchRepository extends JpaRepository<Batch, Long>, JpaSpecificationExecutor<Batch> {
    Optional<Batch> findByCode(String code);
}

Aspect类

package com.example.framework.multitenancy.aspect;

import com.example.logger.LogFactory;
import com.example.logger.Logger;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.hibernate.Filter;
import org.hibernate.Session;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class TenantServiceAspect {
    private static final Logger LOGGER = LogFactory.getLogger(TenantServiceAspect.class);
    @PersistenceContext
    public EntityManager entityManager;

    public TenantServiceAspect() {}

    @Pointcut("execution(* org.springframework.data.jpa.repository.JpaRepository.*(..))")
    void isRepository() {}

    @Pointcut("execution(public * com.example..*.repository..*(..))")
    void isCustomRepository() {}

    @Before("(isCustomRepository() || isRepository())")
    public void beforeExecution(JoinPoint joinPoint) {
        LOGGER.warn("TenantServiceAspect triggered for method: {}", joinPoint.getSignature());
        Filter filter = ((Session)this.entityManager.unwrap(Session.class)).enableFilter("companyFilter").setParameter("companyId", 1L);
        filter.validate();
    }
}

排查发现

  • AspectJ版本差异:Spring Boot 3.3.10使用aspectjweaver 1.9.23,Spring Boot 3.4.0+(含3.4.3)降级为aspectjweaver 1.9.22.1。
  • 依赖变更:Spring Boot 3.4.0起,spring-boot-starter-data-jpa默认不再包含spring-boot-starter-aop依赖,官方发布说明明确移除了该依赖。
  • 怀疑上述变更导致AOP支持在应用重启、高负载场景下出现不一致,进而引发切面偶尔未触发的问题。

建议解决方案

  • 手动添加spring-boot-starter-aop依赖,确保AOP功能完整加载:
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    
  • 升级AspectJ版本至1.9.23或更高,覆盖Spring Boot 3.4.0默认版本:
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.23</version>
    </dependency>
    
  • 配置应用启动防护:利用Spring Boot的ApplicationReadyEvent配合网关/负载均衡器的健康检查机制,确保容器完全初始化后再接收外部请求,避免未就绪时处理请求。

内容的提问来源于stack exchange,提问作者kernel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 11:27:35