跳到主要内容

springfox 源码分析(四) 配置类初始化

时间:2019-5-23 12:46:50

地点:单位、家中

@EnableSwagger2

有了二三章的理解,此时我们再来看EnableSwagger2注解的内容

@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({Swagger2DocumentationConfiguration.class})
public @interface EnableSwagger2 {
}

Swagger2DocumentationConfiguration

该注解没啥好说的,最终是导入Swagger2DocumentationConfiguration的配置类

@Configuration
@Import({ SpringfoxWebMvcConfiguration.class, SwaggerCommonConfiguration.class })
@ComponentScan(basePackages = {
"springfox.documentation.swagger2.mappers"
})
@ConditionalOnWebApplication
public class Swagger2DocumentationConfiguration {

此处的@ComponentScan注解,扫描了springfox.documentation.swagger2.mappers包路径

Mappers

该包路径下包含了众多运用MapStruct组件自动生成的Mapper实体类转换关系,通过扫描注解,自动注入到Spring的容器中

关于MapStruct组件的使用,可参考:springfox 源码分析(二) 初探mapstruct

主要包括如下:

  • LicenseMapper
  • ModelMapper
  • ParameterMapper
  • SecurityMapper
  • SerivceModelToSwagger2Mapper
  • VendorExtensionsMapper

每个Mapper接口都有一个实现类MapperImpl,实现类通过@Component注解注入到Spring的容器中

最重要的是SerivceModelToSwagger2Mapper这个Mapper

该类的作用会聚合使用Model、Parameter、License等Mapper,将springfox中的对象转化为Swagger标准的对象,包括Swagger


@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2018-06-23T17:02:57-0500",
comments = "version: 1.2.0.Final, compiler: javac, environment: Java 1.8.0_151 (Oracle Corporation)"
)
@Component
public class ServiceModelToSwagger2MapperImpl extends ServiceModelToSwagger2Mapper {

@Autowired
private ModelMapper modelMapper;
@Autowired
private ParameterMapper parameterMapper;
@Autowired
private SecurityMapper securityMapper;
@Autowired
private LicenseMapper licenseMapper;
@Autowired
private VendorExtensionsMapper vendorExtensionsMapper;

@Override
public Swagger mapDocumentation(Documentation from) {
if ( from == null ) {
return null;
}

Swagger swagger = new Swagger();

swagger.setVendorExtensions( vendorExtensionsMapper.mapExtensions( from.getVendorExtensions() ) );
swagger.setSchemes( mapSchemes( from.getSchemes() ) );
swagger.setPaths( mapApiListings( from.getApiListings() ) );
swagger.setHost( from.getHost() );
swagger.setDefinitions( modelMapper.modelsFromApiListings( from.getApiListings() ) );
swagger.setSecurityDefinitions( securityMapper.toSecuritySchemeDefinitions( from.getResourceListing() ) );
ApiInfo info = fromResourceListingInfo( from );
if ( info != null ) {
swagger.setInfo( mapApiInfo( info ) );
}
swagger.setBasePath( from.getBasePath() );
swagger.setTags( tagSetToTagList( from.getTags() ) );
List<String> list2 = from.getConsumes();
if ( list2 != null ) {
swagger.setConsumes( new ArrayList<String>( list2 ) );
}
else {
swagger.setConsumes( null );
}
List<String> list3 = from.getProduces();
if ( list3 != null ) {
swagger.setProduces( new ArrayList<String>( list3 ) );
}
else {
swagger.setProduces( null );
}

return swagger;
}
//more...
}

各个Mapper组件的映射关系如下:

Mapper目标类
LicenseMapperio.swagger.models.License通过ApiInfo的属性Lincese构建目标类实体对象
ModelMapperio.swagger.models.Modelspringfox.documentation.schema.Model转化成目标类
ParameterMapperio.swagger.models.parameters.Parameterspringfox.documentation.service.Parameter转化成目标类
SecurityMapperio.swagger.models.auth.SecuritySchemeDefinition
ServiceModelToSwagger2Mapperio.swagger.models.Swagger输出Swagger完整对象

SpringfoxWebMvcConfiguration

Swagger2DocumentationConfiguration源码中,我们看到该Configuration类还引入了SpringfoxWebMvcConfiguration,该类是注入Spring Rest接口相关的配置核心类

先来看源码:


@Configuration
@Import({ ModelsConfiguration.class })
@ComponentScan(basePackages = {
"springfox.documentation.spring.web.scanners",
"springfox.documentation.spring.web.readers.operation",
"springfox.documentation.spring.web.readers.parameter",
"springfox.documentation.spring.web.plugins",
"springfox.documentation.spring.web.paths"
})
@EnablePluginRegistries({ DocumentationPlugin.class,
ApiListingBuilderPlugin.class,
OperationBuilderPlugin.class,
ParameterBuilderPlugin.class,
ExpandedParameterBuilderPlugin.class,
ResourceGroupingStrategy.class,
OperationModelsProviderPlugin.class,
DefaultsProviderPlugin.class,
PathDecorator.class,
ApiListingScannerPlugin.class
})
public class SpringfoxWebMvcConfiguration {

@Bean
public Defaults defaults() {
return new Defaults();
}

@Bean
public DocumentationCache resourceGroupCache() {
return new DocumentationCache();
}

@Bean
public static ObjectMapperConfigurer objectMapperConfigurer() {
return new ObjectMapperConfigurer();
}

@Bean
public JsonSerializer jsonSerializer(List<JacksonModuleRegistrar> moduleRegistrars) {
return new JsonSerializer(moduleRegistrars);
}

@Bean
public DescriptionResolver descriptionResolver(Environment environment) {
return new DescriptionResolver(environment);
}

@Bean
public HandlerMethodResolver methodResolver(TypeResolver resolver) {
return new HandlerMethodResolver(resolver);
}

}

从源码中我们可以看到:

  • 使用import导入ModelConfiguration配置类,该类
  • 使用@ComponentScan注解扫描配置的package包路径,完成Spring的Bean实例注入
  • 使用@EnablePluginRegistries插件机制来完成插件的动态实例Bean注入到Spring容器中,关于Spring Plugin的使用,不明白的可以参考下上一篇文章对Spring Plugin的说明
  • 注入相关Bean的实例对象

ModelsConfiguration

从webmvc配置类导入的Models配置类,我们来看该类的源码

@Configuration
@ComponentScan(basePackages = {
"springfox.documentation.schema"
})
@EnablePluginRegistries({
ModelBuilderPlugin.class,
ModelPropertyBuilderPlugin.class,
TypeNameProviderPlugin.class,
SyntheticModelProviderPlugin.class
})
public class ModelsConfiguration {
@Bean
public TypeResolver typeResolver() {
return new TypeResolver();
}
}

该类的配置和SpringfoxWebMvcConfiguration配置类相似,作用都是扫描包路径,启用PluginRetry进行Spring的实体Bean动态注入

SwaggerCommonConfiguration

Swagger2DocumenationConfiguration导入的第二个配置类SwaggerCommonConfiguration

来看代码:

SwaggerCommonConfiguration.java

@Configuration
@ComponentScan(basePackages = {
"springfox.documentation.swagger.schema",
"springfox.documentation.swagger.readers",
"springfox.documentation.swagger.web"
})
public class SwaggerCommonConfiguration {

}

作用和以上类似

总结

通过@EnableSwagger2注解,我们看到了三个4个Configuration配置类的导入

主要作用:

  • 实体Bean的注入
  • Plugin插件的动态Bean注入
  • 扫描springfox配置的各种package路径

看到这里相信我们还是一头雾水,我们并没有发现springfox何时初始化接口类的.

接下来,我们会针对上面Configuration涉及到的Plugin和@CompnentScan扫描package路径进行一一探索.