简体   繁体   English

如何获得我不“拥有”的自动装配工具的资格

[英]How can I qualify an autowired setter that I don't “own”

The gist is that the Spring Batch (v2) test framework has JobLauncherTestUtils.setJob with an @Autowired annotation. 要点是Spring Batch(v2)测试框架具有带有@Autowired注释的JobLauncherTestUtils.setJob Our test suite has multiple Job class providers. 我们的测试套件有多个Job类提供程序。 Since this class is not something I can modify, I'm not sure how I can qualify which job it gets autowired with, which may be different per test. 由于这个类不是我可以修改的,所以我不确定如何确定自动装配哪个作业,每个测试可能会有所不同。

 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

I've tried adding this JavaConfig which is recognized, but the error says it's still autocalling setJob 我已经尝试添加这个被识别的JavaConfig,但错误说它仍然是自动setJob

@Configuration
public class SpringTestConfiguration
{
@Bean
public JobLauncherTestUtils jobLauncherTestUtilsForSnapshot( final Job generateMetricsSnapshotJob )
{
    JobLauncherTestUtils jobLauncherTestUtils = new JobLauncherTestUtils();
    jobLauncherTestUtils.setJob( generateMetricsSnapshotJob );
    return jobLauncherTestUtils;
}
}

note: I don't require a JavaConfig solution, but it'd be nice. 注意:我不需要JavaConfig解决方案,但它会很好。 Also, I'd like, if possible, to still Autowire fields like JobRepository, as there is only one. 另外,如果可能的话,我希望仍然像JobRepository这样的Autowire字段,因为只有一个。

My solution, when I ran into the same problem, was to restrict the component-scan so that only a single Job bean is created in the test context. 当我遇到同样的问题时,我的解决方案是限制组件扫描,以便在测试上下文中只创建一个Job 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 might need to adjust your package structure for this to work. 您可能需要调整包结构才能使其正常工作。

The solution I came up with 我提出的解决方案

@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 );
    }
}
}

and in the final test 并在最后的测试中

@Autowired
@Qualifier( "jobLauncherTestUtilsForSnapshot" )
protected JobLauncherTestUtils jobLauncherTestUtils;

fairly confident I could just annotate my TestUtils with @Component and name it properly and do the same thing. 相当自信我可以用@Component注释我的TestUtils并正确命名并做同样的事情。

Other kind solution is to inject it via setter. 其他类型的解决方案是通过setter注入它。 I prefer this solution because is clearer and easier. 我更喜欢这种解决方案,因为它更清晰,更容易。

@Configuration
public class SpringTestConfiguration
{
    @Bean
    public JobLauncherTestUtils jobLauncherTestUtilsForSnapshot()
    {
        return new JobLauncherTestUtils() {
            @Override
            @Autowired
            public void setJob(@Qualifier("generateMetricsSnapshotJob") Job job) {
                super.setJob(job);
            }
        };
    }
}

Maybe you could use Spring profiles for that. 也许你可以使用Spring配置文件。 Assign a different profile to every Job provider bean definition (with the annotation @Profile("profileName") , and then activate the profile for the correct provider on the specific test class with the annotation @ActiveProfiles("profileName") . 为每个Job提供程序bean定义(使用注释@Profile("profileName")分配不同的配置文件,然后使用注释@ActiveProfiles("profileName")激活特定测试类上正确提供程序的配置文件。

  1. You can extend AutowiredAnnotationBeanPostProcessor and override inject method. 您可以扩展AutowiredAnnotationBeanPostProcessor并覆盖注入方法。

  2. Remove <context:scan .. /> entries 删除<context:scan .. />条目

  3. Register your bean <bean class ="abCustomAutowiredAnnotationBeanPostProcessor" /> 注册你的bean <bean class ="abCustomAutowiredAnnotationBeanPostProcessor" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM