gpt4 book ai didi

spring - 在 Spring Batch 中访问步骤范围之外的 Bean

转载 作者:行者123 更新时间:2023-12-03 03:38:15 27 4
gpt4 key购买 nike

是否可以访问步骤范围之外定义的 bean?例如,如果我定义策略“strategyA”并将其传递到作业参数中,我希望@Value 解析为strategyA bean。这可能吗?我目前正在通过从 applicationContext 手动获取 bean 来解决该问题。

@Bean
@StepScope
public Tasklet myTasklet(
@Value("#{jobParameters['strategy']}") MyCustomClass myCustomStrategy)

MyTasklet myTasklet= new yTasklet();

myTasklet.setStrategy(myCustomStrategy);

return myTasklet;
}

我希望能够添加更多策略,而无需修改代码。

最佳答案

答案是肯定的。这是比 Spring Batch 更通用的 spring/设计模式问题评估器。
Spring Batch 棘手的部分是配置和理解 bean 创建的范围。
假设您的所有策略都实现策略接口(interface),如下所示:

interface Strategy {
int execute(int a, int b);
};

每个策略都应该实现Strategy并使用@Component注释来允许自动发现新的Strategy。确保所有新策略都放置在正确的包下,以便组件扫描能够找到它们。
例如:

@Component
public class StrategyA implements Strategy {
@Override
public int execute(int a, int b) {
return a+b;
}
}

以上是单例,将在应用程序上下文初始化时创建。
此阶段使用 @Value("#{jobParameters['strategy']}") 还为时过早,因为尚未创建 JobParameter。

因此,我建议稍后在创建 myTasklet 时使用定位器 bean(步骤范围)。

策略定位器类:

public class StrategyLocator {
private Map<String, ? extends Strategy> strategyMap;

public Strategy lookup(String strategy) {
return strategyMap.get(strategy);
}

public void setStrategyMap(Map<String, ? extends Strategy> strategyMap) {
this.strategyMap = strategyMap;
}

}

配置如下:

@Bean
@StepScope
public MyTaskelt myTasklet () {
MyTaskelt myTasklet = new MyTaskelt();
//set the strategyLocator
myTasklet.setStrategyLocator(strategyLocator());
return myTasklet;
}
@Bean
protected StrategyLocator strategyLocator(){
return = new StrategyLocator();
}

要初始化 StrategyLocator,我们需要确保所有策略都已创建。因此,最好的方法是在 ContextRefreshedEvent 事件上使用 ApplicationListener(在此示例中警告策略名称以小写字母开头,更改它很容易...)。

@Component
public class PlugableStrategyMapper implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private StrategyLocator strategyLocator;
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
Map<String, Strategy> beansOfTypeStrategy = applicationContext.getBeansOfType(Strategy.class);
strategyLocator.setStrategyMap(beansOfTypeStrategy);
}

}

tasklet 将保存一个 String 类型的字段,该字段将使用 @Value 注入(inject)策略枚举字符串,并将使用“before step”监听器使用定位器进行解析。

    public class MyTaskelt implements Tasklet,StepExecutionListener {
@Value("#{jobParameters['strategy']}")
private String strategyName;
private Strategy strategy;
private StrategyLocator strategyLocator;

@BeforeStep
public void beforeStep(StepExecution stepExecution) {
strategy = strategyLocator.lookup(strategyName);
}
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
int executeStrategyResult = strategy.execute(1, 2);
}
public void setStrategyLocator(StrategyLocator strategyLocator) {
this.strategyLocator = strategyLocator;
}
}

要将监听器附加到 taskelt,您需要在步骤配置中设置它:

@Bean
protected Step myTaskletstep() throws MalformedURLException {
return steps.get("myTaskletstep")
.transactionManager(transactionManager())
.tasklet(deleteFileTaskelt())
.listener(deleteFileTaskelt())
.build();
}

关于spring - 在 Spring Batch 中访问步骤范围之外的 Bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23560845/

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