我决定将我的服务从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. 只在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
(当然可能会有多个字段)。
所有的解决方案都有其优缺点,但也许还有更好的解决方案?