Spring依赖注入与继承

3

我决定将我的服务从Springsetter-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;
}

FooServiceBaseServiceConcreteService中都被使用。 以下是可能的解决方案:

1. 只在ConcreteService中实现构造函数注入

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

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

我们很好地使用了@RequiredArgsConstructor注解,因为没有必要调用super(在Lombok中不支持调用super)。即使在两个类中有更多的字段,代码看起来也很紧凑。但是我们在BaseService中仍然没有constructor-injection
2. 在BaseService中添加受保护的构造函数,并在ConcreteService构造函数中调用super
@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;
    }
}

主要目标已经实现 - 实现了构造函数注入BaseService看起来很好,但是ConcreteService有一个丑陋的构造函数,需要传递两个服务的所有参数(可能会有很多参数)。让我们再试一次。

3. 将所有字段移动到ConcreteService中,在BaseService中实现受保护的getter以访问FooService

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

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

}

主要目标也已经实现——我们拥有了构造函数注入,构造函数看起来很简洁,但是现在所有BaseService的继承者中都应该有一个FooService(当然可能会有多个字段)。

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

1个回答

2
最终,这并不是一个技术问题,而是一个观点问题。这些优秀的工具(如Lombok、Spring等)旨在使编码更容易,因此在疑惑时,我们应该回到基础。考虑这样一种情况,你从一个抽象类中继承了一个类,并且你没有这些工具。显然,初始化它的正确(也是唯一可能的)方式(如果你想保持代码的解耦)是在继承类中使用构造函数参数(与你的第二个选项非常相似)。
如果看起来很丑陋,且有大量这样的情况,那只意味着设计不够理想,或者在这个领域中存在问题,而不是技术领域中的问题。也许这个类应该分成几个部分?在这种情况下使用抽象类是否比接口/具体类更好?显然,我不知道你的代码需要解决什么样的挑战,但值得考虑的是设计。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接