在以编程方式创建的spring bean中注入存储库

时间:2019-07-08 16:14:30

标签: spring spring-boot

我正在尝试为实体类编写自定义JSF转换器。 我在项目中使用spring-data和spring-boot。

知道我有很多类是这样的:

 @Component("myFirstConverter")
 class MyFirstConverter implements Converter {
    @Autowired
    private MyFirstRepository myFirstRepository;

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, 
                              String value) {
    return myFirstRepository.findOne(Long.parseLong(value));
    }
    //...

}

我创建了自定义类EntityConverter。它与CrudRepository一起使用。但是我不明白如何以编程方式创建bean数组并将其注入到每个bean对应的存储库中。

知道我尝试使用以下代码编写 @Configuration 类:

 @Configuration
 class MyConfig extends WebMvcConfigurerAdapter  
       @Bean
       public static BeanFactoryPostProcessor registerConverters(ApplicationContext context) {
    Map<String, Class<? extends CrudRepository>> converterBeans = new HashMap<>();
    converterBeans.put("firstEntity", firstEntityRepository.class);
    converterBeans.put("secondEntity", secondEntity.class);
    return factory -> {
        for (val entry : converterBeans.entrySet()) {
            CrudRepository bean = context.getBean(entry.getValue()
            factory.registerSingleton(entry.getKey()
            .concat("Converter"), new EntityConverter(
                    entry.getKey(), bean));
        }
    };

但是它不起作用。应用程序初始化失败。

 19:07:59.546 [WARN ] o.s.c.support.AbstractApplicationContext:551  - 
    Exception encountered during context initialization - cancelling 
    refresh attempt: 
    org.springframework.beans.factory.BeanCreationException: Error 
    creating bean with name 'myFirstRepository': Cannot create inner bean 
    '(inner bean)#1fdfafd2' of type 
    [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting 
    bean property 'entityManager'; nested exception is 
    org.springframework.beans.factory.BeanCreationException: Error 
    creating bean with name '(inner bean)#1fdfafd2': Cannot resolve 
    reference to bean 'entityManagerFactory' while setting constructor 
    argument; nested exception is 
    org.springframework.beans.factory.BeanCreationException: Error 
    creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fe46103]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fe46103.<init>()Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fumoRepository': Cannot create inner bean '(inner bean)#1fdfafd2' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#1fdfafd2': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fe46103]: No default constructor found; nested exception is java.lang.NoSuchMethodException: 
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfigurati 
    on$$EnhancerBySpringCGLIB$$fe46103.<init>()

UPD:

允许WiPU解决该问题。我这样更改了registerConverters方法:

 @Configuration
 class MyConfig extends WebMvcConfigurerAdapter  
       @Bean
       public static BeanFactoryPostProcessor 
     registerConverters(ApplicationContext context) {
        Map<String, Class<? extends CrudRepository>> converterBeans = new HashMap<>();
    converterBeans.put("firstEntity", firstEntityRepository.class);
    converterBeans.put("secondEntity", secondEntity.class);
    return factory -> {
        BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) 
        factory;
        for (val entry : converterBeans.entrySet()) {
              BeanDefinitionBuilder b =

   BeanDefinitionBuilder.genericBeanDefinition(EntityConverter.class)
                            .addPropertyReference("repository", entry.getKey().concat("Repository"))
                    ;
            beanFactory.registerBeanDefinition(entry.getKey().concat("Converter"), b.getBeanDefinition());
            factory.registerSingleton(entry.getKey()
            .concat("Converter"), new EntityConverter(
                    entry.getKey(), bean));
        }
    };

1 个答案:

答案 0 :(得分:1)

Spring无法根据显示的Exception实例化您的Repository Bean。

在装入所有bean定义但尚未实例化之后,将调用BeanFactoryPostProcessor。您可以在此处找到详细信息:Link

在所有其他Bean已经正确实例化之后,您可以尝试在此过程中稍后注册Bean。您可以在此处找到一些详细信息:Link

此时,您所有的存储库都应该已经正确实例化,您只需添加其他EntityConverter

或者,如果您需要将EntityConverter注入其他bean,则可以注册BeanDefinitons。然后,当存储库已经创建时,Spring将实例化您的bean。 Link to JavaDoc

致谢, WiPu