Spring Boot泛型类Autowired依赖注入问题及替代方案咨询
问题解决方案
问题1:如何让Spring不注入AbstractEntityService构造器中的Bean?
核心问题是抽象类AbstractEntityService不需要被标记为@Service,Spring仅需管理具体的子类Bean。要注入OtherService,可通过以下两种方式避免Spring尝试实例化抽象类:
方案1:构造器传递依赖(推荐,符合依赖注入规范)
移除抽象类的@Service注解,将OtherService加入抽象类构造器,子类实例化时自动传递该依赖:
// 抽象类无需@Service abstract class AbstractEntityService<T>( private val entityRepository: AbstractRepository<T>, protected val otherService: OtherService ) { fun getEntity(entityId: Long): T = entityRepository.findById(entityId) fun commonMethodUsingOtherService() { // 使用otherService实现通用逻辑 otherService.doSomething() } } // 子类保留@Service,构造器接收所有依赖并传递给父类 @Service class MyEntityService( myRepository: MyRepository, otherService: OtherService ) : AbstractEntityService<MyEntity>(myRepository, otherService) { // 自定义业务方法 }
方案2:方法注入(避免子类传递依赖)
同样移除抽象类的@Service注解,用@Autowired标记setter方法,Spring实例化子类时会自动调用该方法注入OtherService:
abstract class AbstractEntityService<T>( private val entityRepository: AbstractRepository<T>, ) { protected lateinit var otherService: OtherService @Autowired fun setOtherService(otherService: OtherService) { this.otherService = otherService } fun getEntity(entityId: Long): T = entityRepository.findById(entityId) fun commonMethodUsingOtherService() { otherService.doSomething() } } @Service class MyEntityService( myRepository: MyRepository ) : AbstractEntityService<MyEntity>(myRepository) { // 自定义业务方法 }
问题2:不使用继承的技术方案实现通用逻辑抽象
推荐用组合+委托的方式(Kotlin对委托支持友好),将通用逻辑封装到独立类中,具体Service通过组合复用,避免继承带来的框架限制:
步骤1:定义通用操作接口
interface EntityServiceOperations<T> { fun getEntity(entityId: Long): T fun commonMethodUsingOtherService() }
步骤2:实现通用逻辑
class DefaultEntityServiceOperations<T>( private val repository: AbstractRepository<T>, private val otherService: OtherService ) : EntityServiceOperations<T> { override fun getEntity(entityId: Long): T = repository.findById(entityId) override fun commonMethodUsingOtherService() { // 通用逻辑实现 otherService.doSomething() } }
步骤3:具体Service复用通用逻辑
利用Kotlin的委托特性,直接复用DefaultEntityServiceOperations的实现:
@Service class MyEntityService( private val myRepository: MyRepository, private val otherService: OtherService ) : EntityServiceOperations<MyEntity> by DefaultEntityServiceOperations(myRepository, otherService) { // 自定义业务方法 fun customBusinessMethod() { // 个性化逻辑 } }
如果不想用委托,也可以直接通过组合调用:
@Service class MyEntityService( private val myRepository: MyRepository, private val otherService: OtherService ) { private val defaultOperations = DefaultEntityServiceOperations(myRepository, otherService) // 复用通用方法 fun getEntity(entityId: Long): MyEntity = defaultOperations.getEntity(entityId) fun commonMethodUsingOtherService() = defaultOperations.commonMethodUsingOtherService() // 自定义方法 }
额外优化:通过配置类批量创建通用实例
如果有多个Service需要复用通用逻辑,可以通过@Configuration批量生成DefaultEntityServiceOperations实例:
@Configuration class EntityServiceConfig { @Bean fun myEntityServiceOperations( myRepository: MyRepository, otherService: OtherService ): EntityServiceOperations<MyEntity> { return DefaultEntityServiceOperations(myRepository, otherService) } // 其他实体的通用实例同理 }
内容的提问来源于stack exchange,提问作者David Kubecka
相关产品推荐
相关产品推荐

