有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

参数化类上的java Spring自动连接问题

我已经为这个问题挣扎了一段时间,浏览了很多文章,但没有找到解决方案。感谢您对以下问题的帮助

我需要能够在服务类中自动连接EntityManager,但会引发异常。默认构造函数可能因为类型擦除而出现问题,因此我尝试使用带参数的构造函数来设置类型。如何自动连接用户类型的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) 个答案

  1. # 1 楼答案

    EntityManager类上可能缺少@Component注释

    自动连线构造函数需要一个未注入的类实体

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

    试试看

    @Autowired(required=true)
        public EntityManager() {
    
        }
    
  2. # 2 楼答案

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