如何在@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
相关产品推荐
相关产品推荐

