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

如何让Hibernate Cache自定义RegionFactory获取Spring注入的Bean?

问题场景

自定义SpringRedisRegionFactory继承RegionFactoryTemplate,尝试通过SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this)注入RedisConnectionFactory,运行时抛出错误:

Current WebApplicationContext is not available for processing of SpringRedisRegionFactory: Make sure this class gets constructed in a Spring web application after the Spring WebApplicationContext has been initialized. Proceeding without injection.

此前在EntityListeners中使用相同注入方法可正常工作,但在RegionFactory中无效。

核心原因

RegionFactory的初始化时机早于Spring WebApplicationContext的就绪时间,或者该类未纳入Spring Bean生命周期管理,导致SpringBeanAutowiringSupport无法获取有效上下文完成注入。

解决方案

方案一:将RegionFactory纳入Spring Bean管理

让Spring直接管理SpringRedisRegionFactory实例,自动完成依赖注入:

  1. 给类添加@Component注解,使其被Spring扫描并托管:
@Component
public class SpringRedisRegionFactory extends RegionFactoryTemplate {

  @Autowired
  private transient RedisConnectionFactory redisConnectionFactory;

  // 原有方法实现...
}
  1. 配置Hibernate使用该Spring托管的RegionFactory(以Spring Boot为例):
# application.properties
spring.jpa.properties.hibernate.cache.region.factory_class=com.yourpackage.SpringRedisRegionFactory

方案二:手动通过ApplicationContext工具类完成注入

如果无法将RegionFactory纳入Spring Bean管理,可通过静态持有上下文的工具类手动注入:

  1. 创建ApplicationContext持有类:
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static ApplicationContext getContext() {
        return context;
    }
}
  1. 修改registerNewStorageAccess方法,手动触发注入:
private DomainDataStorageAccess registerNewStorageAccess(final String regionName) {

    if (storageAccesses == null) {
        throw new IllegalStateException("prepareForUse was not executed yet");
    }

    ApplicationContext context = ApplicationContextHolder.getContext();
    if (context != null) {
        context.getAutowireCapableBeanFactory().autowireBean(this);
    } else {
        throw new IllegalStateException("ApplicationContext not initialized");
    }

    final var storageAccess = new SpringRedisStorageAccess(regionName, redisConnectionFactory);
    storageAccesses.add(storageAccess);
    return storageAccess;
}

方案三:利用RegionFactory的prepareForUse方法延迟注入

RegionFactoryTemplate的prepareForUse方法执行时机晚于初始化阶段,此时Spring上下文已就绪,可将注入逻辑移至该方法:

@Override
public void prepareForUse(DomainDataRegionBuildingContext buildingContext) {
    super.prepareForUse(buildingContext);
    // 在此处执行注入,确保上下文已初始化
    SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}

private DomainDataStorageAccess registerNewStorageAccess(final String regionName) {

    if (storageAccesses == null) {
        throw new IllegalStateException("prepareForUse was not executed yet");
    }

    // 无需再手动调用注入,prepareForUse已完成注入
    final var storageAccess = new SpringRedisStorageAccess(regionName, redisConnectionFactory);
    storageAccesses.add(storageAccess);
    return storageAccess;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 05:40:25