簡體   English   中英

關於參數化類的Spring自動裝配問題

[英]Spring autowiring issues on paramaterized class

我已經為這個問題苦苦掙扎了一段時間,並且瀏覽了很多文章,但是找不到解決方案。 感謝您對以下問題的幫助。

我需要能夠在服務類中自動裝配EntityManager,但是會引發異常。 默認構造函數可能由於類型擦除而存在問題,因此我嘗試使用帶有參數的構造函數來設置Type。 如何自動連接User類型的EntityManager?

public interface IEntityManager<T extends IDomain<ID>, ID extends Serializable> {

    T findById(ID id, boolean lock);

    T save(T entity);

    void delete(T entity);
}

public class EntityManager<T extends IDomain<ID>, ID extends Serializable> 
        implements IEntityManager<T, ID> {

    private Class<T> entity;

    @Autowired(required=true)
    private SessionFactory sessionFactory;

    /*
    @SuppressWarnings("unchecked")
    public EntityManager() {
        this.entity = (Class<T>) ((ParameterizedType) getClass()
                            .getGenericSuperclass()).getActualTypeArguments()[0];

    } */

    @Autowired(required=true)
    public EntityManager(Class<T> entity) {
        this.entity = entity;
    }
}

@Service("UserService")
@Transactional
public class UserServiceImpl implements IUserService {

    @Autowired  
    EntityManager<User, Integer> entityManager;
}

這是例外:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'UserService': Injection of autowired dependencies failed; 
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.test.dummy.persistence.manager.EntityManager com.test.dummy.service.UserServiceImpl.entityManager; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.test.dummy.persistence.manager.EntityManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)

Spring 無法推斷出需要在EntityManager的構造函數中注入User.class來滿足UserServiceImpl的依賴性。

如果使用Spring 4 ,則可以定義EntityManager<User, Integer>類型的Bean:

@Configuration
public class Config {
      @Bean 
      public EntityManager<User, Integer> userEntityManager() {
            new EntityManager(User.class);
      } 
}

編輯:或定義一個BeanDefinitionRegistryPostProcessor ,它將檢查需要EntityManager作為依賴項的bean,標識所需的類型,構造所需類型的新EntityManager bean並將其添加到bean注冊表中。

 @Component
 public class MyEntityManagerBeanDefinitionRegistryPostProcessor implements
                                                       BeanDefinitionRegistryPostProcessor {


   @Override
   public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory)
       throws BeansException {
     for (String beanName : beanFactory.getBeanDefinitionNames()) {
       final BeanDefinition beanDefinition = getOriginatingBeanDefinition(
           beanFactory.getBeanDefinition(beanName));
       final Class<?> beanClass = getClass(beanDefinition.getBeanClassName());
       if (beanClass != null) {
         ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() {
           public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {

             if (field.isAnnotationPresent(Autowired.class) || field.isAnnotationPresent(
                 Inject.class)) {
               if (field.getGenericType() instanceof ParameterizedType) {
                 final ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
                 final Class<?> rawType = (Class) parameterizedType.getRawType();
                 if (rawType.equals(EntityManager.class)) {
                   final Class<?> typeArgument = (Class<?>) parameterizedType.getActualTypeArguments()[0];
                   beanFactory.registerSingleton(field.getName(), new EntityManager(typeArgument));
                 }
               }
             }
           }
         });
       }
     }
   }

   private Class<?> getClass(String className) throws BeansException {
     if (className != null) {
       try {
         return Class.forName(className);
       } catch (ClassNotFoundException e) {
         throw new BeanInitializationException("beanClass not found", e);
       }
     }
     return null;
   }

   private BeanDefinition getOriginatingBeanDefinition(BeanDefinition beanDefinition) {
     while(beanDefinition.getOriginatingBeanDefinition() != null) {
       beanDefinition = beanDefinition.getOriginatingBeanDefinition();
     }
     return beanDefinition;
   }


   @Override
   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {  }
 }

最后,看起來您實際需要的是使用Spring Data Jpa ,從本質上講,您可以通過定義如下接口來定義參數化DAO:

package com.myapp.repository; 

@Repository
public interface UserRepository extends JpaRepository<User, Long> {}

您啟用它:

@Configuration
@EnableJpaRepositories(basePackages = "com.myapp.repository")
public class Config {


}

然后,您注入UserRepository

@Autowired
private UserRepository userRepository;

Spring將注入一個基本的DAO實現。

您可能在EntityManager類上缺少@Component批注。

自動裝配的構造函數需要一個未注入的類實體。

@Autowired(required=true)
public EntityManager(Class<T> entity) {
    this.entity = entity;
}

嘗試

@Autowired(required=true)
    public EntityManager() {

    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM