参数化类的Spring自动装配问题

时间:2014-08-15 17:30:06

标签: java spring hibernate

我一直在努力解决这个问题并浏览了很多文章,但无法找出解决方案。感谢您对以下问题的帮助。

我需要能够在服务类中自动装配EntityManager,但会引发异常。由于类型擦除,默认构造函数可能存在问题,因此我尝试使用带参数的构造函数来设置Type。如何自动装配用户类型的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)

2 个答案:

答案 0 :(得分:3)

Spring 无法推断需要在User.class的构造函数中注入EntityManager以满足UserServiceImpl中的depadenency。

如果您使用的是 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实现。

答案 1 :(得分:-1)

您的EntityManager类可能缺少 @Component 注释。

自动装配的构造函数需要一个未注入的类实体。

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

尝试

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

    }