Spring注入存储库与构造函数中的普通属性混合



我有Service类和Repository接口(Spring Data(。我还有一个抽象类:

public abstract class TestingMethod {
public TestingMethod() {
timeSum = 0;
}
protected long timeSum;
}

以及扩展它的类:

@Component
public class LimitTestingMethod extends TestingMethod {
@Autowired
private GeoTestDataRepository geoTestDataRepository;
private final int limitSize;
public LimitTestingMethod(int limitSize) {
super();
this.limitSize = limitSize;
}
}

在我的Service中,我想创建LimitTestingMethod的实例并设置其参数limitSize。类似于:

LimitTestingMethod ltm3 = new LimitTestingMethod(3);
LimitTestingMethod ltm10 = new LimitTestingMethod(10);

但我错了:

描述:中构造函数的参数0com.exence.postgiscma.testingMethod.LimitTestingMethod需要一个bean未能找到类型为"int"的。行动:考虑定义配置中类型为"int"的bean。

有可能实现我想要的目标吗?

一切顺利!

//编辑

正如我在评论中看到的那样,这是一种糟糕的做法。所以也许有人会给我建议如何更好地进行项目?将repo作为构造函数中的参数传递是一个好的解决方案吗(我想不是,但我不知道如何做得更好(?

LimitTestingMethod ltm3 = new LimitTestingMethod(3, geoTestDataRepository);

有没有一个好的、优雅的解决方案?

当您在Spring范围之外创建实例时,您当前的解决方案将无法工作。错误来自于这样一个事实,即您已经用@Component对其进行了注释,它将在启动时检测到它并尝试创建一个bean,但失败了。

要解决这个问题,你可以做两件事中的一件。

  1. 让Spring通过使用ApplicationContext作为工厂来处理bean的创建,提供额外的参数使bean原型具有作用域
  2. 在使用ApplicationContext手动创建实例之后,让Spring处理注入

ApplicationContext用作工厂

首先,使您的bean成为一个原型,以便在需要时构建它。

@Component
@Scope(
ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class LimitTestingMethod extends TestingMethod { ... }

现在,在启动过程中不会创建实例。在您的服务中注入ApplicationContext并使用getBean方法来获得所需的实例。

public class Service {
@Autowired
private ApplicationContext ctx;

public void yourMethod() {
LimitTestingMethod ltm3 = ctx.getBean(LimitTestingMethod.class, 3);
LimitTestingMethod ltm10 = ctx.getBean(LimitTestingMethod.class, 10);
}
}

这将允许Spring使用为构造函数传递的值创建实例,并进行自动连接。

创建后注入

另一个解决方案是手动创建实例,然后让Spring处理自动连接。这样一来,您将失去AOP功能,并且只能获得自动布线。

首先从LimitTestingMethod中删除@Component注释,这样在启动过程中就不会检测到它。

public class LimitTestingMethod extends TestingMethod { ... }

现在,在您的服务中自动连接ApplicationContext,并在创建bean之后使用它来注入依赖项。

public class Service {
@Autowired
private ApplicationContext ctx;

public void yourMethod() {
LimitTestingMethod ltm3 = new LimitTestingMethod(3);
LimitTestingMethod ltm10 = new LimitTestingMethod(10);
ctx.getAutowireCapableBeanFactory().autowireBean(lmt3);
ctx.getAutowireCapableBeanFactory().autowireBean(lmt10);
}
}

两者都将实现您想要的,但是,现在您的代码直接依赖于Spring API。因此,与其这样做,您可能更适合使用另一个选项,即通过构造函数注入LimitTestingMethod的所有内容,并自己传递存储库。

使用构造函数创建实例

public class LimitTestingMethod extends TestingMethod {
private final GeoTestDataRepository geoTestDataRepository;
private final int limitSize;
public LimitTestingMethod(int limitSize, GeoTestDataRepository geoTestDataRepository) {
this.limitSize=limitSize;
this.geoTestDataRepository=geoTestDataRepository;
}
}

然后,您可以简单地自动连接服务类中的存储库,并根据需要创建实例(或者创建一个包含创建此对象复杂性的工厂(。

public class Service {
@Autowired
private GeoTestDataRepository repo;

public void yourMethod() {
LimitTestingMethod ltm3 = new LimitTestingMethod(3, repo);
LimitTestingMethod ltm10 = new LimitTestingMethod(10, repo);
}
}

最新更新