Java 基于相互依赖性的springbean排序
我有一个Java8/Spring应用程序。定义了一个接口Java 基于相互依赖性的springbean排序,java,spring,sorting,Java,Spring,Sorting,我有一个Java8/Spring应用程序。定义了一个接口DataCalculator: public interface Calculator { public void calculate(Data data); } 我有几个实现这个接口的具体类,它们都用@Component注释,所以它们是SpringBean(singleton)。我想运行所有这些,因此我使用了自动连线列表: public class MyApplication { private List<Calc
DataCalculator
:
public interface Calculator
{
public void calculate(Data data);
}
我有几个实现这个接口的具体类,它们都用@Component
注释,所以它们是SpringBean(singleton)。我想运行所有这些,因此我使用了自动连线列表:
public class MyApplication
{
private List<Calculator> calculators;
@Autowired //Technically not needed, added for clarity
public MyApplication(List<Calculator> calculators)
{
this.calculators = calculators;
}
public void calculateAll(Collection<Data> dataCollection)
{
for(Data data : dataCollection)
{
for(Calculator calculator : this.calculators)
{
calculator.calculate(data);
}
}
}
}
公共类MyApplication
{
私人名单计算器;
@自动连线//技术上不需要,为清晰起见添加
公共MyApplication(列表计算器)
{
这个。计算器=计算器;
}
公共void calculateAll(收集数据收集)
{
用于(数据:数据收集)
{
for(计算器:this.calculators)
{
计算器。计算(数据);
}
}
}
}
这是可行的,但我现在偶然发现了一个要求,即某些计算器依赖于其他计算器先完成。我认为有三种方法可以实现这一点,每种方法都有利弊:
@Order(x)
注释。赞成:简洁到程序。缺点:如果依赖性很高或很深,开发人员添加或编辑计算器是非常麻烦的。这些信息分散在所有的计算器上,而不是集中提供@CalcDependency(value=OtherCalculator.class)
,并在计算器列表上运行拓扑排序算法,以便在使用它们之前对它们进行排序。赞成:排序逻辑在一个地方,每个计算器都表示它们所依赖的内容,而不是它们所具有的任意“顺序”。易于插入新计算器:只需声明依赖项,而不是顺序。(如果检测到周期性依赖项,则应抛出错误)缺点:大多数编程工作量似乎都太大了李>
想法?Spring是否有某种方式来声明在自动关联列表时需要考虑的依赖项
我知道spring有一个
@dependsOn
注释,但在这种情况下这似乎没有什么用处。您可以编写包装类,它有一些顺序字段,您可以用来排序计算器,或者简单地将该字段添加到bean中,或者添加更多的接口。。。选项由您选择
然后,简单地按“顺序”字段对计算器进行排序,并使用foreach
下面的评论中询问了一个例子。(这完全不是产品代码,只是给您展示一个示例)
可能的话,你能提供一个简短的代码示例吗?@AuntJemima更新了答案,希望它能对你有所帮助。在我的用例中,使用Spring的
@Order
注释有什么附加值?当然,你可以使用Order注释,它可以根据你的需要工作。您还可以声明一些常量类,这些常量类将显示“排序级别”,例如:NO_DEPENDENCIES=1,dependens_SOMETHING_FROM_LEVEL_1=2 dependens_SOMETHING_FROM_LEVEL_2=3。。另外,当您从上下文接收集合时,需要对它们进行排序,而不是它们添加到上下文中的顺序。因此,在这种情况下,您可以轻松忽略DependsOn注释。此外,您需要以某种方式对收藏进行排序。您可以轻松地编写自己的比较器,并以某种方式列出依赖项,从而解决问题。
package org.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.util.Comparator;
import java.util.List;
@Configuration
@ComponentScan
public class Main {
@Autowired
List<Calculator> calculators;
public void start() {
calculators.stream().sorted(Comparator.comparing(Calculator::getOrder)).forEach(Calculator::calculate);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(Main.class);
ctx.refresh();
Main main = ctx.getBean(Main.class);
main.start();
}
}
interface Calculator {
void calculate();
int getOrder();
}
@Component
class FirstCalc implements Calculator {
@Override
public void calculate() {
System.out.println(String.format("firstCalc with order %s", getOrder()));
}
@Override
public int getOrder() {
return 1;
}
}
@Component
class SecondCalc implements Calculator {
@Override
public void calculate() {
System.out.println(String.format("secondCalc with order %s", getOrder()));
}
@Override
public int getOrder() {
return 1;
}
}
@Component
class ThirdCalc implements Calculator {
@Override
public void calculate() {
System.out.println(String.format("thirdCalc with order %s should be 3rd", getOrder()));
}
@Override
public int getOrder() {
return 2;
}
}
@Component
class FourthCalc implements Calculator {
@Override
public void calculate() {
System.out.println(String.format("lastCalc with order %s should be last", getOrder()));
}
@Override
public int getOrder() {
return 3;
}
}
firstCalc with order 1
secondCalc with order 1
thirdCalc with order 2 should be 3rd
lastCalc with order 3 should be last