覆盖Spring定义:Spring Bean Annotation @Primary

时间:2016-01-25 18:00:42

标签: java spring spring-mvc

覆盖bean定义在我看来比我想象的更难。 首先,我想保持开/关原则。

我正在使用Springfox,它将提供基于Spring Mapping的swagger json。 Springfox由我必须提供的Config类加载:

@EnableWebMvc
@Configuration
@Import({Swagger2DocumentationConfiguration.class})
@ComponentScan(basePackages = {"special.package.swagger"})
public class ApplicationSwaggerConfig {

    @Bean
    public Docket swaggerApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("rest-api")
                .select()
                .build()
                .pathMapping("/rest-api");
    }
   ...

当然,我不想改变Swagger2DocumentationConfiguration类(遵循开放/封闭原则)但改变ServiceModelToSwagger2Mapper的行为。

为此,我在“special.package.swagger”文件夹中创建了一个MyServiceModelToSwagger2Mapper类,例如:

@Component
@Primary
public class MyServiceModelToSwagger2Mapper extends ServiceModelToSwagger2MapperImpl {

    @Override
    public Swagger mapDocumentation(Documentation from) {
        System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n******************** Override works!!!\n");
        return super.mapDocumentation(from);
    }

}

Spring加载组件,解决了歧义问题,但是覆盖不起作用。有谁知道为什么!?

编辑:@smarquis评论帮了很多忙。 Spring工作正常。

我不小心添加了多个版本的springfox库。应用程序服务器加载了两个库并丢失了。一旦类路径问题得到解决,覆盖就会完美地运行。

2 个答案:

答案 0 :(得分:1)

这是由于构建java配置的spring的方式 - 内部代理和东西变得非常复杂。

我不记得确切的原因,但如果你这样做你的覆盖工作:

@EnableWebMvc
@Configuration
@Import({Swagger2DocumentationConfiguration.class})
//@ComponentScan(basePackages = {"springfoxswagger.specialpackageswagger"})
public class ApplicationSwaggerConfig {

    @Bean
    public Docket swaggerApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("rest-api")
                .select()
                .build()
                .pathMapping("/rest-api");
    }


    @Bean
    public springfox.documentation.swagger2.mappers.ServiceModelToSwagger2Mapper mapper() {
        return new  ServiceModelToSwagger2MapperImpl() {
            public Swagger mapDocumentation(Documentation from) {
                System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n******************** Override works!!!\n");
                return super.mapDocumentation(from);
            }

        };
    }

}

它也更简单,可以说。

编辑

似乎不适用于OP,所以我进一步调查了一下。

  • 如果您只是在没有@Primary的情况下添加ServiceModelToSwagger2MapperImpl的第二个实现,则会得到异常“...期望的单个匹配bean但找到2”
  • 如果您使用注释添加它,您将获得OP所说的内容(弹簧开始,但覆盖不起作用)。
  • 如果你再次在我的解决方案中添加@Bean,那么使得ServiceModelToSwagger2MapperImpl的三个实现,并且根本没有任何@Primary,spring启动并且覆盖工作。
  • 请注意,您不需要在bean上使用@Primary注释。

    2016-01-26 08:50:26.594  INFO 58548 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 22 ms
    

    ********************覆盖工作!!!

  • 添加@BeanNameAware或@AnnotationConfigDriven等“简单”解决方案是行不通的。 IMO OP遇到了Spring Java Config错误或限制;我没有看到他的解决方案无效的任何理由。

答案 1 :(得分:0)

尝试将@AnnotationDrivenConfig放在您的课​​堂上并尝试:

@EnableWebMvc
@Configuration
@AnnotationDrivenConfig
@Import({Swagger2DocumentationConfiguration.class})
public class ApplicationSwaggerConfig {

    @Bean
    public Docket swaggerApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("rest-api")
                .select()
                .build()
                .pathMapping("/rest-api");
    }

    @Bean
    @Primary
    public MyServiceModelToSwagger2Mapper mapper() {
        return new MyServiceModelToSwagger2Mapper();
    }
}

MyServiceModelToSwagger2Mapper类:

public class MyServiceModelToSwagger2Mapper extends ServiceModelToSwagger2MapperImpl {

    @Override
    public Swagger mapDocumentation(Documentation from) {
        System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n******************** Override works!!!\n");
        return super.mapDocumentation(from);
    }
}