我如何才能限定我不 "own" 的自动装配 setter
How can I qualify an autowired setter that I don't "own"
要点是 Spring Batch (v2) 测试框架有 JobLauncherTestUtils.setJob
和 @Autowired
注释。我们的测试套件有多个 Job
class 供应商。由于这个 class 不是我可以修改的东西,我不确定我如何才能限定它自动连接的作业,每个测试可能会有所不同。
STDOUT [WARN ] [2015.04.15 11:14:42] support.GenericApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobLauncherTestUtilsForSnapshot': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.batch.test.JobLauncherTestUtils.setJob(org.springframework.batch.core.Job); nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.batch.core.Job] is defined: expected single matching bean but found 2: coverageRuleBatch,generateMetricsSnapshotJob
我尝试添加这个被识别的 JavaConfig,但错误提示它仍在自动调用 setJob
@Configuration
public class SpringTestConfiguration
{
@Bean
public JobLauncherTestUtils jobLauncherTestUtilsForSnapshot( final Job generateMetricsSnapshotJob )
{
JobLauncherTestUtils jobLauncherTestUtils = new JobLauncherTestUtils();
jobLauncherTestUtils.setJob( generateMetricsSnapshotJob );
return jobLauncherTestUtils;
}
}
注意:我不需要 JavaConfig 解决方案,但它会很好。另外,如果可能的话,我希望仍然自动装配像 JobRepository 这样的字段,因为只有一个。
或许您可以使用 Spring 配置文件。为每个 Job
提供者 bean 定义分配一个不同的配置文件(带有注释 @Profile("profileName")
,然后在特定测试 class 上为正确的提供者激活配置文件,带有注释 @ActiveProfiles("profileName")
.
当我 运行 遇到同样的问题时,我的解决方案是限制组件扫描,以便在测试上下文中只创建一个作业 bean。
@Configuration
@ComponentScan(basePackages={
"com.example.batch.jobs.metrics", //package where generateMetricsSnapshotJob is the only job
"com.example.batch.common",
"..."
})
public class SpringTestConfiguration
{
@Bean
public JobLauncherTestUtils jobLauncherTestUtils()
{
//generateMetricsSnapshotJob and other requirements will be autowired
return new JobLauncherTestUtils();
}
}
您可能需要调整您的包结构才能使其正常工作。
You can extend AutowiredAnnotationBeanPostProcessor and override
inject method.
删除 <context:scan .. />
个条目
注册您的 bean <bean class ="a.b.CustomAutowiredAnnotationBeanPostProcessor" />
我想到的解决方案
@Configuration
public class SpringBatchTestConfiguration
{
@Bean
public static JobLauncherTestUtils jobLauncherTestUtilsForSnapshot()
{
return new SnapshotJobLauncherTestUtils();
}
public static class SnapshotJobLauncherTestUtils extends JobLauncherTestUtils
{
@Override
@Qualifier( "generateMetricsSnapshotJob" )
public void setJob( final Job job )
{
super.setJob( job );
}
}
}
并在期末考试中
@Autowired
@Qualifier( "jobLauncherTestUtilsForSnapshot" )
protected JobLauncherTestUtils jobLauncherTestUtils;
我非常有信心我可以用 @Component 注释我的 TestUtils 并正确命名它并做同样的事情。
另一种解决方案是通过 setter 注入它。我更喜欢这个解决方案,因为它更清晰、更容易。
@Configuration
public class SpringTestConfiguration
{
@Bean
public JobLauncherTestUtils jobLauncherTestUtilsForSnapshot()
{
return new JobLauncherTestUtils() {
@Override
@Autowired
public void setJob(@Qualifier("generateMetricsSnapshotJob") Job job) {
super.setJob(job);
}
};
}
}
要点是 Spring Batch (v2) 测试框架有 JobLauncherTestUtils.setJob
和 @Autowired
注释。我们的测试套件有多个 Job
class 供应商。由于这个 class 不是我可以修改的东西,我不确定我如何才能限定它自动连接的作业,每个测试可能会有所不同。
STDOUT [WARN ] [2015.04.15 11:14:42] support.GenericApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobLauncherTestUtilsForSnapshot': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.batch.test.JobLauncherTestUtils.setJob(org.springframework.batch.core.Job); nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.batch.core.Job] is defined: expected single matching bean but found 2: coverageRuleBatch,generateMetricsSnapshotJob
我尝试添加这个被识别的 JavaConfig,但错误提示它仍在自动调用 setJob
@Configuration
public class SpringTestConfiguration
{
@Bean
public JobLauncherTestUtils jobLauncherTestUtilsForSnapshot( final Job generateMetricsSnapshotJob )
{
JobLauncherTestUtils jobLauncherTestUtils = new JobLauncherTestUtils();
jobLauncherTestUtils.setJob( generateMetricsSnapshotJob );
return jobLauncherTestUtils;
}
}
注意:我不需要 JavaConfig 解决方案,但它会很好。另外,如果可能的话,我希望仍然自动装配像 JobRepository 这样的字段,因为只有一个。
或许您可以使用 Spring 配置文件。为每个 Job
提供者 bean 定义分配一个不同的配置文件(带有注释 @Profile("profileName")
,然后在特定测试 class 上为正确的提供者激活配置文件,带有注释 @ActiveProfiles("profileName")
.
当我 运行 遇到同样的问题时,我的解决方案是限制组件扫描,以便在测试上下文中只创建一个作业 bean。
@Configuration
@ComponentScan(basePackages={
"com.example.batch.jobs.metrics", //package where generateMetricsSnapshotJob is the only job
"com.example.batch.common",
"..."
})
public class SpringTestConfiguration
{
@Bean
public JobLauncherTestUtils jobLauncherTestUtils()
{
//generateMetricsSnapshotJob and other requirements will be autowired
return new JobLauncherTestUtils();
}
}
您可能需要调整您的包结构才能使其正常工作。
You can extend AutowiredAnnotationBeanPostProcessor and override inject method.
删除
<context:scan .. />
个条目注册您的 bean
<bean class ="a.b.CustomAutowiredAnnotationBeanPostProcessor" />
我想到的解决方案
@Configuration
public class SpringBatchTestConfiguration
{
@Bean
public static JobLauncherTestUtils jobLauncherTestUtilsForSnapshot()
{
return new SnapshotJobLauncherTestUtils();
}
public static class SnapshotJobLauncherTestUtils extends JobLauncherTestUtils
{
@Override
@Qualifier( "generateMetricsSnapshotJob" )
public void setJob( final Job job )
{
super.setJob( job );
}
}
}
并在期末考试中
@Autowired
@Qualifier( "jobLauncherTestUtilsForSnapshot" )
protected JobLauncherTestUtils jobLauncherTestUtils;
我非常有信心我可以用 @Component 注释我的 TestUtils 并正确命名它并做同样的事情。
另一种解决方案是通过 setter 注入它。我更喜欢这个解决方案,因为它更清晰、更容易。
@Configuration
public class SpringTestConfiguration
{
@Bean
public JobLauncherTestUtils jobLauncherTestUtilsForSnapshot()
{
return new JobLauncherTestUtils() {
@Override
@Autowired
public void setJob(@Qualifier("generateMetricsSnapshotJob") Job job) {
super.setJob(job);
}
};
}
}