在通用超类中自动装配通用组件

时间:2016-05-09 09:26:56

标签: java spring dependency-injection spring-boot

我在Spring 4.0(使用Spring Boot)环境中遇到以下情况:

映射界面

public interface EntityModelMapper<ENTITY extends AbstractEntity, MODEL extends AbstractModel>{ }

映射实施

@Component
public class ProductEntityModelMapper implements EntityModelMapper<Product, ProductModel>{ }

服务

public interface CrudService<MODEL extends AbstractModel>{ }

我想做一个像这样的抽象超类服务

public abstract AbstractCrudService<ENTITY extends AbstractEntity, MODEL extends AbstractModel> implements CrudService<MODEL>{

@Autowired
private EntityModelMapper<ENTITY, MODEL> mapper;

  public EntityModelMapper<ENTITY, MODEL> getMapper(){ 
      return mapper; 
  }
}

所以我可以实现这样的实现

@Service
public ProductCrudService extends AbstractCrudService<Product, ProductModel>{

  public void someMethod(Product product){
    ProductModel model = getMapper().map(product);
  }

}

但Spring告诉我,它无法在服务类中注入EntityModelMapper的限定bean。这种情况是否可能,我做错了什么,还是我在推动Spring的依赖注射?

堆栈跟踪:

org.springframework.beans.factory.BeanCreationException:
 Error creating bean with name 'productCrudService':
 Injection of autowired dependencies failed;
 nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field:
 private com.flycatcher.seagull.mapper.EntityModelMapper 
com.flycatcher.seagull.facade.service.crud.AbstractCrudService.mapper;
 nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
 No qualifying bean of type [com.flycatcher.seagull.mapper.EntityModelMapper] 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)}

1 个答案:

答案 0 :(得分:1)

根据这个: https://spring.io/blog/2013/12/03/spring-framework-4-0-and-java-generics 从Spring 4.0版本开始就可以实现。

那对我也没有用。 (同样的例外,我使用4.2.3)。 所以尝试升级到最新版本 - 4.2.6。

如果它仍然无法正常工作, 您可以改为使用@Qualifier注释并将EntityModelMapper自动装配为子类中的接口,并将getMapper定义为abstract:

  @Component
  @Qualifier("productEntityModelQualifier")
  public class ProductEntityModelMapper implements EntityModelMapper<Product, ProductModel>{ }

然后在ProductCrudService:

@Service
public ProductCrudService extends AbstractCrudService<Product, ProductModel>{

  @Autowired
  @Qualifier("productEntityModelQualifier")
  EntityModelMapper<Product, ProductModel> mapper;

  @Override
  protected EntityModelMapper<Product, ProductModel> getMapper(){return mapper;}

  public void someMethod(Product product){
    ProductModel model = getMapper().map(product);
  }

}