如何在NoRepositoryBean的实现中自动连接Bean



使用Spring Boot/Spring Data,我向所有存储库添加了一个自定义函数。这是我所做的一个片段:

所以我有了我的存储库接口:

@NoRepositoryBean
public interface RepositoryBase<T, ID extends Serializable> extends JpaRepository<T, ID> {

及其实现

public class RepositoryBaseImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements RepositoryBase<T, ID> {
@Autowired 
MessageLocale messageLocale; // <- this is a classic spring bean which is not injected in this spot (always null)
private EntityManager entityManager;
public RepositoryBaseImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.entityManager = entityManager;
}
//... My custom methods here

和我的配置:

@Configuration
@EnableJpaRepositories(basePackages = "my.base.pkg", repositoryBaseClass = RepositoryBaseImpl.class)
public class RepositoryConfig {
}

我的自定义方法工作正常,但我需要注入messageLocal

Autowired在RepositoryBaseImpl中不起作用(我认为这是因为它不是bean)

我无法在RepositoryBaseImpl上添加@Repository,因为我在其父接口上使用@NoRepositoryBean

那么有没有办法注入messageLocale?

基于@Prabhakar D的评论,我将根据我的需求发布我的答案(除了@EnableMongoRepository和其他一些小修改外,还使用@EnableJpaRepository)

在@EnableJpaRepositorys注释中,添加repositoryFactoryBeanClass:

@EnableJpaRepositories(basePackages = "my.base.pkg", repositoryBaseClass = RepositoryBaseImpl.class, repositoryFactoryBeanClass = MyRepositoryFactoryBean.class)

关键是你可以在存储库中使用@AutowireFactoryBBeanClass

创建一个repositoryFactoryBeanClass并在其中自动连接您的bean。这是一个spring bean,它在overrided方法createRepositoryFactory:中创建了一个自定义JpaRepositoryFactory

public class MyRepositoryFactoryBean<T extends JpaRepository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T, S, ID> {
@Autowired
private MessageLocale messageLocale;
public MyRepositoryFactoryBean(Class repositoryInterface) {
super(repositoryInterface);
}
@Override
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new MyJpaRepositoryFactory(entityManager, messageLocale);
}
}

现在,创建自定义工厂(MyJpaRepositoryFactory),并使用重写的方法getTargetRepository来创建基本存储库的实例(RepositoryBaseImpl)。在这里,您可以将您的bean注入其构造函数:

public class MyJpaRepositoryFactory extends JpaRepositoryFactory {
private EntityManager entityManager;
private MessageLocale messageLocale;
public MyJpaRepositoryFactory(EntityManager entityManager, MessageLocale messageLocale) {
super(entityManager);
this.entityManager = entityManager;
this.messageLocale = messageLocale;
}
//****************** Edit ********************
//starting from spring boot 2.1.0, getTargetRepository(RepositoryInformation information) was made final. So you can't override it anymore. You will need to override getTargetRepository(RepositoryInformation information, EntityManager entityManager)
//@Override
//protected Object getTargetRepository(RepositoryInformation information) {
//    return new RepositoryBaseImpl(getEntityInformation(information.getDomainType()), entityManager, messageLocale);
//}
@Override
protected JpaRepositoryImplementation<?, ?> getTargetRepository(RepositoryInformation information, EntityManager entityManager) {
return new RepositoryBaseImpl(getEntityInformation(information.getDomainType()), entityManager, messageLocale);
}
//****************** End Edit ******************** 
}

现在,只需修改RepositoryBaseImpl的构造函数,使其可以接受所需的Bean:

public class RepositoryBaseImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements RepositoryBase<T, ID> {
private MessageLocale messageLocale;
private EntityManager entityManager;
//if you are using IntelliJ, it can show you an error saying "Could not autowire. No beans of JpaEntityInformation". It is just a bug in IntelliJ
public RepositoryBaseImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager, MessageLocale messageLocale) {
super(entityInformation, entityManager);
this.entityManager = entityManager;
this.messageLocale = messageLocale;
}
//... My custom methods here

既然您的messageLocal已注入到BaseRepositoryImpl中,您就可以在自定义方法中使用它,而无需在参数中传递它

希望这能帮助

最新更新