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

如何在@NoRepositoryBean的实现类中自动装配Spring Bean?

解决Spring Data JPA自定义Repository实现中依赖注入为null的问题

首先得明确为什么@Autowired注入MessageLocale会失败:Spring Data JPA的Repository实例是动态生成的代理对象,你的RepositoryBaseImpl只是作为代理的底层实现类,并不是Spring容器直接管理的Bean,所以Spring不会对它执行依赖注入操作,自然@Autowired的字段会是null。

下面给你两种可行的解决方案,按需选择:


方案一:通过ApplicationContextAware手动获取Bean

这是最简单直接的方式,让你的实现类实现ApplicationContextAware接口,拿到Spring上下文后手动获取所需Bean。

步骤1:修改RepositoryBaseImpl实现ApplicationContextAware

public class RepositoryBaseImpl<T, ID extends Serializable> 
    extends SimpleJpaRepository<T, ID> 
    implements RepositoryBase<T, ID>, ApplicationContextAware {

    private ApplicationContext applicationContext;
    private MessageLocale messageLocale;

    // 必须保留这个构造器,Spring Data JPA会通过它创建实例
    public RepositoryBaseImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        // 在这里初始化MessageLocale,或者在需要使用时再获取
        this.messageLocale = applicationContext.getBean(MessageLocale.class);
    }

    // 你的自定义方法示例
    @Override
    public String getLocalizedErrorMessage(String errorCode) {
        return messageLocale.getMessage(errorCode);
    }
}

步骤2:指定Spring Data使用这个基类

在Spring Boot启动类上通过@EnableJpaRepositories的repositoryBaseClass属性指定:

@SpringBootApplication
@EnableJpaRepositories(repositoryBaseClass = RepositoryBaseImpl.class)
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

方案二:自定义RepositoryFactoryBean实现构造器注入

如果想更贴合Spring的依赖注入思想,避免直接操作ApplicationContext,可以通过自定义工厂Bean来实现构造器注入。

步骤1:修改RepositoryBaseImpl添加构造器参数

public class RepositoryBaseImpl<T, ID extends Serializable> 
    extends SimpleJpaRepository<T, ID> 
    implements RepositoryBase<T, ID> {

    private final MessageLocale messageLocale;

    // 扩展构造器,新增MessageLocale参数
    public RepositoryBaseImpl(
        JpaEntityInformation<T, ?> entityInformation, 
        EntityManager entityManager,
        MessageLocale messageLocale) {
        super(entityInformation, entityManager);
        this.messageLocale = messageLocale;
    }

    // 自定义方法示例
    @Override
    public String getLocalizedErrorMessage(String errorCode) {
        return messageLocale.getMessage(errorCode);
    }
}

步骤2:自定义RepositoryFactory

public class CustomRepositoryFactory extends JpaRepositoryFactory {

    private final EntityManager entityManager;
    private final MessageLocale messageLocale;

    public CustomRepositoryFactory(EntityManager entityManager, MessageLocale messageLocale) {
        super(entityManager);
        this.entityManager = entityManager;
        this.messageLocale = messageLocale;
    }

    @Override
    protected RepositoryComposition.RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
        RepositoryComposition.RepositoryFragments fragments = super.getRepositoryFragments(metadata);
        // 如果当前Repository继承了RepositoryBase,就添加自定义实现片段
        if (RepositoryBase.class.isAssignableFrom(metadata.getRepositoryInterface())) {
            JpaEntityInformation<?, Serializable> entityInfo = getEntityInformation(metadata.getDomainType());
            RepositoryBaseImpl<?, ?> customImpl = new RepositoryBaseImpl<>(entityInfo, entityManager, messageLocale);
            fragments = fragments.append(RepositoryComposition.RepositoryFragment.implemented(customImpl));
        }
        return fragments;
    }
}

步骤3:自定义RepositoryFactoryBean

public class CustomRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> 
    extends JpaRepositoryFactoryBean<T, S, ID> {

    private MessageLocale messageLocale;

    public CustomRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
        super(repositoryInterface);
    }

    @Autowired
    public void setMessageLocale(MessageLocale messageLocale) {
        this.messageLocale = messageLocale;
    }

    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new CustomRepositoryFactory(entityManager, messageLocale);
    }
}

步骤4:指定使用自定义工厂Bean

在启动类上配置:

@SpringBootApplication
@EnableJpaRepositories(factoryBeanClass = CustomRepositoryFactoryBean.class)
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

方案对比

  • 方案一:实现成本低,适合快速解决简单场景,但直接操作ApplicationContext属于“手动获取Bean”,不够优雅。
  • 方案二:完全遵循依赖注入思想,代码结构更清晰,适合复杂项目或对代码规范有要求的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:53:00