繁体   English   中英

覆盖 spring-boot 自动配置

[英]Overwriting spring-boot autoconfiguration

在覆盖特定的自动配置时,我对 spring-boot 的行为有点困惑。

我喜欢部分覆盖 BatchAutoConfiguration,但我想,我的问题不是特定于 BatchAutoConfiguration。 实际上,我只想“覆盖”此类的两个方法: public BatchDatabaseInitializer batchDatabaseInitializer()public ExitCodeGenerator jobExecutionExitCodeGenerator()

因此,我编写了以下代码: package ch.test.autoconfig.autoconfigure;

import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration;
import org.springframework.boot.autoconfigure.batch.BatchDatabaseInitializer;
import org.springframework.boot.autoconfigure.batch.BatchProperties;
import org.springframework.boot.autoconfigure.batch.JobExecutionExitCodeGenerator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcOperations;

import javax.sql.DataSource;

/**
 * I'm using the same annotations as defined in BatchAutoConfiguration...
 */
@Configuration
@ConditionalOnClass({ JobLauncher.class, DataSource.class, JdbcOperations.class })
@AutoConfigureAfter(HibernateJpaAutoConfiguration.class)
@ConditionalOnBean(JobLauncher.class)
@EnableConfigurationProperties(BatchProperties.class)

// ... but I add @AutoConfigureBefore(BatchAutoConfiguration.class) to take precedence over BatchAutoConfiguration
@AutoConfigureBefore(BatchAutoConfiguration.class)
public class JavabatchAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnBean(DataSource.class)
    public BatchDatabaseInitializer batchDatabaseInitializer() {
        System.out.println("Entering overwritten batchDatabaseInitializer");
        return new BatchDatabaseInitializer();
    }

    @Bean
    @ConditionalOnMissingBean
    public ExitCodeGenerator jobExecutionExitCodeGenerator() {
        System.out.println("Entering overwritten jobExecutionExitCodeGenerator");
        return new JobExecutionExitCodeGenerator();
    }
}

正如代码中提到的,我对类和方法使用完全相同的注释,因为它们在 BatchAutoConfiguration.class 中BatchAutoConfiguration.class 唯一的例外是添加@AutoConfigureBefore(BatchAutoConfiguration.class) 由于这应该优先于 BatchAutoConfiguration,我认为这会“覆盖”原始文件。

要测试的是,我使用以下 pom.xml:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">


    <modelVersion>4.0.0</modelVersion>

    <groupId>ch.test.autoconfig</groupId>
    <artifactId>auto_config_test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.3.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency>
    </dependencies>
</project>

我正在使用这个简单的工作和一个主要方法:

package ch.test.autoconfig;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

/**
 * Created by U802552 on 01.06.2015.
 */
@SpringBootApplication
@EnableBatchProcessing
public class MainJob {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    @Bean
    protected Tasklet tasklet() {
        return new Tasklet() {
            public RepeatStatus execute(StepContribution contribution,
                                        ChunkContext context) {
                return RepeatStatus.FINISHED;
            }
        };
    }

    @Bean
    public Job job() throws Exception {
        return this.jobs.get("job").start(step1()).build();
    }

    @Bean
    protected Step step1() throws Exception {
        return this.steps.get("step1").tasklet(tasklet()).build();
    }

    public static void main(String[] args) throws Exception {
        // switch on  Auto-Configuration-Report
        System.setProperty("debug","true");
        SpringApplication.run(MainJob.class, args);
    }
}

我希望我的两个被覆盖的方法被调用,但正如 Auto-Configuration-Report 所述,由于缺少“JobLauncher”实例,我的 JavabatchAutoConfiguration 类具有“否定匹配”。 正如报告还指出的那样,原始 BatchAutoConfiguration 类与相同的ConditionalOnBean检查具有正匹配。

如果我在 class 上评论@ConditionalOnBean(JobLauncher.class)并在batchDatabaseInitializer -method 上评论@ConditionalOnBean(JobLauncher.class) @ConditionalOnBean(DataSource.class) ,一切都按预期工作。

有人对这种行为有解释吗?

感谢 Hansjörg

你正在使它变得复杂。 您唯一需要做的就是创建一个配置来定义您要使用的 2 个特定 bean。

@Configuration
public class MyBatchConfiguration {

    @Bean
    public ExitCodeGenerator myExitCodeGenerator() {
        return new MyExitCodeGenerator();
    }

    @Bean
    public BatchDatabaseInitializer myBatchDatabaseInitializer() {
        return new MyBatchDatabaseInitializer();
    }

}

这就是你所需要的。

我认为 Hansjörg 和 M. 是对的。 “方法名称”应与特定 AutoConfiguration 使用的相同。

原因:我不确定,如果 ApplicationContext 中存在相同的类型是 spring 省略创建该类型的唯一标准。 至少预选赛必须是一样的?!

暂无
暂无

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

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