代码之家  ›  专栏  ›  技术社区  ›  ihebiheb

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

  •  0
  • ihebiheb  · 技术社区  · 6 年前

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

    @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?

    0 回复  |  直到 6 年前
        1
  •  0
  •   ihebiheb    6 年前

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

    在@EnableJpaRepositories注释中,添加repositoryFactoryBeanClass:

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

    关键是,您可以在repositoryFactoryBeanClass中使用@Autowire

    创建RepositoryFactoryBean类并在其中自动关联bean。这是一个SpringBean,它在重写的方法createRepositoryFactory中创建自定义JParePositionFactory:

    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)并使用覆盖的方法getTargetPository创建基本存储库的实例(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中,您就可以在自定义方法中使用它,而无需在参数中传递它

    希望这能帮助别人