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

Posted

技术标签:

【中文标题】在通用超类中自动装配通用组件【英文标题】:Autowiring a generic component in a generic superclass 【发布时间】:2016-09-03 20:56:04 【问题描述】:

我在一个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:
 创建名为“productCrudService”的 bean 时出错:
 注入自动装配的依赖项失败;
 嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:
 私人 com.flycatcher.seagull.mapper.EntityModelMapper
com.flycatcher.seagull.facade.service.crud.AbstractCrudService.mapper;
 嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:
 没有为依赖找到 [com.flycatcher.seagull.mapper.EntityModelMapper] 类型的合格 bean:
 预计至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。
 依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true)

【问题讨论】:

【参考方案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 定义为抽象:

  @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);
  


【讨论】:

直接在服务实现中注入 EntityModelMapper 对我有用。我想要做的是将它注入抽象类,以便每个服务实现都可以访问其特定的 EntityModelMapper 实现。 (即 ProductCrudService 将在运行时准备好 EntityModelMapper。) 我明白你想要什么。阅读我的答案的第一段

以上是关于在通用超类中自动装配通用组件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot 中实现通用 JPA 存储库 - 它可以自动装配到任何实体/类类型的 Spring 服务中

无法在 Spring Boot 的组件类中自动装配推土机 Mapper

通过注解实现自定义Spring Boot Starter自动装配

如何自动装配在 SpringBoot 应用程序中具有带参数的构造函数的组件

装配Bean

Spring框架开发底层的@Component 通用组件模式@Service 服务模式@Configuration 配置模式等注解装配技术详解