gpt4 book ai didi

java - Spring Beans 中的构造函数参数太多

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:47:55 26 4
gpt4 key购买 nike

在我的代码中有一个 Bean AdminAdmin 的其中一项操作是创建Task启动它们。

Task 执行的操作相当复杂。所以它被分成几个不同的 Step 类。

这就是我的代码的样子

public interface Admin{
void start();

//other methods
}

public class AdminImpl implements Admin{
private BeanA bean1;
private BeanB bean2;
//other fields

public Admin(BeanA bean1,
BeanB bean2,
BeanC bean3
//Lot more parameters
BeanO bean15
){
this.bean1 = bean1;
this.bean2 = bean2;
//and so on
}

public void start(){
return new Task(bean1, bean2, bean3,...).start()
}

//other methods
}

public class Task{
private BeanA bean1;
private BeanB bean2;
//other fields
public Task(BeanA bean1,
BeanB bean2,
BeanC bean3
//Lot more parameters
){
//bind parameters to fields
}

public void start(){
new Step1(bean1, bean2,.. other parameters).do();
new Step2(bean3, bean7,.. other parameters).do();
//more steps
}
}

@Configuration
public class MyConfiguration{
@Bean
public Admin admin(BeanA bean1, BeanB bean2....){
return new AdminImpl(bean1, bean2...);
}
}

如您所见,每个 Step 类都有 2 或 3 个 Bean 依赖项。 Step 类不是 Spring Beans,因此它们从 Task 传递依赖关系。 Task 也不是 Spring Bean,因此它从 Admin 获取依赖项。这导致 Admin 有太多依赖项(~15)。

我试过这个:https://dzone.com/articles/autowiring-spring-beans-into-classes-not-managed-by-spring .

基本上,您创建一个名为 BeanUtil 的服务 Bean,它是 ApplicationContextAware。静态方法 getBean 使用 ApplicationContext 获取 bean。

Step 类现在看起来像这样:

class Step{
public Step(){
BeanA bean1 = BeanUtil.getBean(BeanA.class);
BeanB bean2 = BeanUtil.getBean(BeanB.class);
}

public void do(){
//do stuff
}
}

这解决了最初的问题,但后来我在测试时遇到了困难。这就是测试类现在的样子。

 @ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class Step1Test extends AbstractTestNGSpringContextTests {

@Test
public void test(){
Step1 step = new Step().do();
}

@Configuration
static class MockConfiguration {

@Bean
public BeanA beanA() {
BeanA mockBeanA=Mockito.mock(BeanA.class);
// set behavior of mock
return mockBeanA;
}

@Bean
public BeanUtil beanUtil(){
return new BeanUtil();
}
}
}

如果不创建不同的配置类,您就无法更改不同测试用例的模拟行为。这感觉就像通过创造另一个问题来解决一个问题。

这是 Spring 开发人员面临的一个普遍问题,较高抽象级别的类最终会具有过多的依赖项吗?还是我的设计有问题?处理或避免这种情况的正确方法是什么?

其他看似相似但不相似的问题

编辑: 我从 user7 那里得到的一个建议是我将 BeanX 分组并将抽象传递给管理员。这些 bean 没有任何我可以利用的逻辑分组。此外,许多步骤 需要对bean 的完全访问(访问接口(interface)中的所有方法)。这会导致抽象变得臃肿。

最佳答案

您可以将步骤 Spring bean 作为原型(prototype) bean(因为它们是有状态的,并且您每次都需要不同的实例),然后注入(inject) Provider<Step>在您的任务 bean 中(如果我理解正确的话,它可以是单例 bean)。

例如:

public class Step1 {
private Bean1 bean1;
private Bean2 bean2;

private final String someValue;
private final String someOtherValue;

public Step(String someValue, String someOtherValue) {
this.someValue = someValue;
this.someOtherValue = someOtherValue;
}

@Autowired
public void setBean1(Bean1 bean1) {
this.bean1 = bean1;
}

@Autowired
public void setBean2(Bean2 bean2) {
this.bean2 = bean2;
}

do() {
// ...
}
}

然后在您的配置类中,您将各种步骤定义为 beans,方法需要所需的参数:

@Bean
@Scope("prototype")
public Step1 step1(String someValue, String someOtherValue) {
return new Step(someValue, someOtherValue);
}

然后在 Task bean 中,您注入(inject)一个 ObjectProvider<Step1> :

private ObjectProvider<Step1> stepProvider;

public Service(ObjectProvider<Step1> step1Provider) {
this.stepProvider = stepProvider;
}

public void start() {
Step1 step1 = step1Provider.getObject("a", "b");
step1.do();
}

关于java - Spring Beans 中的构造函数参数太多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49207421/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com