Spring 依赖注入与继承

问题描述 投票:0回答:2

我决定将我的服务从

Spring
setter-injection
更新为
constructor-injection
,以逐步摆脱循环依赖。问题是服务使用继承,父服务和子服务都有自己的字段。所以问题是 - 使用
Lombok
实现构造函数注入的最佳方法是什么。 这是原始代码的示例:

@Setter(onMethod_ = @Autowired)
public abstract class BaseService {
    
    protected FooService fooService;
}

@Service
@Setter(onMethod_ = @Autowired)
public class ConcreteService extends BaseService {
    
    private BarService barService;
}

FooService
用于
BaseService
ConcreteService
。 以下是可能的解决方案:

1.

constructor-injection
中实施
ConcreteService

@Setter(onMethod_ = @Autowired)
public abstract class BaseService {
    
    protected FooService fooService;
}

@Service
@RequiredArgsConstructor
public class ConcreteService extends BaseService {
    
    private final barService BarService;
}

我们很好地利用了

@RequiredArgsConstructor
注解,因为不需要调用
super
super
不支持调用
Lombok
)。即使两个类中都有更多字段,代码看起来也很紧凑。但我们在
constructor-injection
中仍然没有
BaseService

2. 将受保护的构造函数添加到

BaseService
并在
super
构造函数中调用
ConcreteService

@RequiredArgsConstructor(AccessLevel.PROTECTED)
public abstract class BaseService {
    
    protected final FooService fooService;
}

@Service
public class ConcreteService extends BaseService {
    
    private final BarService barService;
    
    public ConcreteService(FooService fooService, BarService barService) {
        super(fooService);
        this.barService = barService;
    }
}

实现的主要目标 - 实现了

constructor-injection
BaseService
看起来不错,但是
ConcreteService
有一个丑陋的构造函数,其中应该传递两个服务的所有参数(并且可能有很多参数)。我们再试一次吧。

3. 将所有字段移至

ConcreteService
,在
getter
中实现受保护的
BaseService
以访问
FooService

public abstract class BaseService {
    
    protected abstract FooService getFooService();
}

@Service
@RequiredArgsConstructor
public class ConcreteService extends BaseService {
    
    private final FooService fooService;
    private final BarService barService;

}

主要目标也实现了 - 我们有一个

constructor-injection
,构造函数看起来很干净,但现在我们应该在所有
FooService
继承者中都有一个
BaseService
(当然可以有多个字段)。

所有解决方案都有其优点和缺点,但也许有更好的解决方案?

java spring inheritance dependency-injection lombok
2个回答
2
投票

归根结底,这与其说是一个技术问题,不如说是一个意见问题。这些出色的工具(即 Lombok、Spring 等)是为了让编码变得更容易,所以当有疑问时,我们应该回到基础知识。考虑这样一种情况:您从抽象类继承了一个类,但您没有这些工具。显然,初始化它的正确(也是唯一可能)方法(如果您想让代码保持解耦)是使用继承类中的构造函数参数(也与您的第二个选项非常相似)。

如果看起来很丑而且数量很多,那只能说明设计不太理想,可能是这个领域而不是技术领域出了问题。也许班级应该分成几个?在这种情况下,使用抽象类比使用接口/具体类更好吗?显然,我不知道您的代码必须解决的挑战,但值得考虑设计。


0
投票

您找到好的解决方案了吗?我对此(相当广泛)询问了 o1-preview,除了使用组件服务作为子类中的字段或返回基于字段的注入(这就是 chatpgt 推荐的)之外,似乎没有什么好的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.