关于参数化类的Spring自动装配问题 [英] Spring autowiring issues on paramaterized class

查看:76
本文介绍了关于参数化类的Spring自动装配问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一段时间以来,我一直在努力解决这个问题,并且浏览了许多文章,但找不到解决方案.感谢您对以下问题的帮助.

I have been struggling with this issue for a while and have browsed a lot of articles, but couldnt figure out the solution. Appreciate your help with the issue below.

我需要能够在服务类中自动装配EntityManager,但是会引发异常.默认的构造函数可能由于类型擦除而存在问题,因此我尝试使用带有参数的构造函数来设置Type.如何自动连接类型为User的EntityManager?

I need to be able to autowire the EntityManager in the service class, but throws an exception. The default constructor probably has issues because of type erasure and so I tried using a constructor with parameters to set the Type. How do I autowire EntityManager of type User?

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 cannot deduce that it need to Inject User.class in the constructor of EntityManager to satisfy the depdenency in UserServiceImpl.

如果使用的是 Spring 4 ,则可以定义EntityManager<User, Integer>类型的Bean:

If you are using Spring 4, You can to define a bean of type EntityManager<User, Integer>:

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

修改: 或定义 BeanDefinitionRegistryPostProcessor ,它将检查需要EntityManager作为依赖项的bean,确定所需的类型,为所需的类型构造新的EntityManager bean,并将其添加到bean注册表中.

Or define a BeanDefinitionRegistryPostProcessor that will check for beans that require EntityManager as dependency, identify the required type, construct the new EntityManager bean for the required type and add it to the bean registry.

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

Finally, it looks like what you actually need is to use Spring Data Jpa which, in essence, lets you define a parameterized DAO by defining an interface like this:

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实现.

And Spring will inject a basic DAO implementation.

这篇关于关于参数化类的Spring自动装配问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆