Используя 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-компонент)
Я не могу добавить @Repository в RepositoryBaseImpl, потому что я использую @NoRepositoryBean в его родительском интерфейсе.
Итак, есть ли способ внедрить messageLocale?




Основываясь на комментарии @Prabhakar D, я опубликую свой ответ в соответствии со своими потребностями (используя @EnableJpaRepositories помимо @EnableMongoRepositories и некоторые другие небольшие модификации)
В аннотацию @EnableJpaRepositories добавьте репозиторийFactoryBeanClass:
@EnableJpaRepositories(basePackages = "my.base.pkg", repositoryBaseClass = RepositoryBaseImpl.class, repositoryFactoryBeanClass = MyRepositoryFactoryBean.class)
Главное, вы можете использовать @Autowire внутри репозиторияFactoryBeanClass.
Создайте репозиторийFactoryBeanClass и автоматически подключите в нем свои компоненты. Это Spring bean, который создает пользовательский JpaRepositoryFactory в переопределенном методе createRepositoryFactory:
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, вы можете использовать его в своих пользовательских методах без необходимости передавать его в параметрах.
Надеюсь, что это поможет кому-то
Проверьте этот пост. https://stackoverflow.com/questions/45345287/how-to-inject-a-dependency-into-a-repository-base-class