调用指定Repository方法时获取entityManager并合并两个切点的实现方案
解决方案
要实现仅当MyRepo方法被调用时才触发EntityManager的filter设置逻辑,避免无关调用触发catch分支,有两种可行方案:
方案1:使用AspectJ cflow 控制流切点(需要原生AspectJ支持)
利用AspectJ的cflow指示符匹配处于MyRepo方法调用流中的createEntityManager调用,直接合并两个切点逻辑,无需额外状态管理:
@Pointcut("execution(* com.package.repository.MyRepo.*(..))") public void insideRepository() {} @Pointcut("execution(* javax.persistence.EntityManagerFactory+.createEntityManager(..))") public void createEntityManager() {} // 组合切点:仅当createEntityManager发生在MyRepo方法的调用流程中时匹配 @Pointcut("createEntityManager() && cflow(insideRepository())") public void createEntityManagerInRepoFlow() {} @Before("insideRepository()") public void enableFilter(JoinPoint jp) { System.out.println("Inside repo"); } @AfterReturning(pointcut = "createEntityManagerInRepoFlow()", returning = "entityManager") public void enableFilter(EntityManager entityManager) { // 仅MyRepo调用时才会进入该逻辑,确认场景必需要filter的话可以直接去掉try-catch entityManager.unwrap(Session.class).enableFilter("myFilter"); }
如果你的项目已经启用了原生AspectJ编译/织入,优先选择该方案,逻辑更简洁。
方案2:基于ThreadLocal状态标记(兼容Spring AOP默认环境)
如果你用的是Spring默认的代理模式AOP(不支持cflow指示符),可以用ThreadLocal存储当前线程是否处于MyRepo调用状态,在EntityManager创建后先判断状态再执行filter设置:
// 线程隔离的状态标记,记录当前线程是否处于MyRepo方法调用中 private static final ThreadLocal<Boolean> IN_REPO_CALL = ThreadLocal.withInitial(() -> false); @Pointcut("execution(* com.package.repository.MyRepo.*(..))") public void insideRepository() {} @Pointcut("execution(* javax.persistence.EntityManagerFactory+.createEntityManager(..))") public void createEntityManager() {} @Before("insideRepository()") public void markRepoCallStart() { IN_REPO_CALL.set(true); } // 无论MyRepo方法执行成功还是抛出异常,都要清空标记,避免内存泄漏和状态误判 @After("insideRepository()") public void markRepoCallEnd() { IN_REPO_CALL.remove(); } @AfterReturning(pointcut = "createEntityManager()", returning = "entityManager") public void enableFilter(EntityManager entityManager) { // 非MyRepo调用场景直接跳过逻辑 if (!IN_REPO_CALL.get()) { return; } try { entityManager.unwrap(Session.class).enableFilter("myFilter"); } catch (Exception e) { System.out.println("No filter myFilter for this entity"); } }
内容的提问来源于stack exchange,提问作者SBDev
相关产品推荐
相关产品推荐

