我有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,但失败了。
要解决这个问题,你可以做两件事中的一件。
- 让Spring通过使用
ApplicationContext
作为工厂来处理bean的创建,提供额外的参数和使bean原型具有作用域 - 在使用
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);
}
}