栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot 自动配置原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot 自动配置原理

目录
      • @EnableAutoConfiguration
      • spring.factories中AutoConfiguration相关配置
      • AutoConfigurationimportFilter的过滤机制
      • @AutoConfigurationPackage 自动配置要应用的包
      • AutoConfigurationimportSelector 自动配置导入选择器
      • 自动配置导入监听器的日志打印
      • 自动配置原理总结

 

使用的springboot源码版本 2.3.12.RELEASE
 

@EnableAutoConfiguration

@EnableAutoConfiguration 是 @SpringBootApplication 包含的三大注解之一,用于启用自动装配

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@AutoConfigurationPackage
@import(AutoConfigurationimportSelector.class)
public @interface EnableAutoConfiguration {

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	Class[] exclude() default {};

	String[] excludeName() default {};

}

启用自动配置后,springboot会跟根据classpath包含的jar包、应用中定义的bean推测需要自动配置的bean。如果手动进行了配置,则不会再使用对应的自动配置。

可以用 exclude 或 excludeName 排除不使用的自动配置类,exclude 是以Class对象形式指定,excludeName 是以字符串形式指定类名。
 

@EnableAutoConfiguration 包含了2个注解

  • @AutoConfigurationPackage:指定自动配置要应用的包,即要对应用中的哪些包使用自动配置
  • @import(AutoConfigurationimportSelector.class):导入 AutoConfigurationimportSelector 组件,这个类用于导入、筛选spring.factories中指定的自动配置类

 

spring.factories中AutoConfiguration相关配置

spring-boot-autoconfigure 的 spring.factories,相关内容如下

# 自动配置导入监听器
# AutoConfigurationimportListener 继承的是jdk的事件监听器 EventListener,不是spring的 ApplicationListener
org.springframework.boot.autoconfigure.AutoConfigurationimportListener=
org.springframework.boot.autoconfigure.condition.ConditionevaluationReportAutoConfigurationimportListener


# 自动配置类导入过滤器
org.springframework.boot.autoconfigure.AutoConfigurationimportFilter=
org.springframework.boot.autoconfigure.condition.OnBeanCondition,
org.springframework.boot.autoconfigure.condition.OnClassCondition,
org.springframework.boot.autoconfigure.condition.onWebApplicationCondition


# 自动配置类
# 注解是 @interface 类型,本质是一种特殊的接口,此处的 EnableAutoConfiguration 即 @EnableAutoConfiguration 注解
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

自动配置相关的有3项

  • AutoConfigurationimportListener:指定自动配置导入监听器。会在导入自动配置时调用对应的回调方法,后面会提到。
  • EnableAutoConfiguration:指定自动配置类。springboot提供了大量的自动配置类,涵盖了常用的组件、框架。
  • AutoConfigurationimportFilter:指定自动配置类的过滤器。

EnableAutoConfiguration 指定的是springboot提供的全部自动配置类,AutoConfigurationimportFilter 用于对自动配置类进行筛选、过滤,根据classpath、应用中定义的bean推断可能要使用的自动配置类,最后只导入可能要使用的自动配置类。

 

AutoConfigurationimportFilter的过滤机制

AutoConfigurationimportFilter 是如何对自动配置类进行筛选过滤的?是如何推断可能要使用的自动配置类的?这其实是一个问题。
 

先看 spring.factories 中指定的自动配置类,随便点开一个,基本都是:类上使用了 @Configuration 标注为bean,类中使用@Bean标注了bean,使用 @Conditional 系列注解校验这2个注解的是否满足条件。
 

@Conditional 系列注解的介绍可以查看我的另一篇博文:
https://blog.csdn.net/chy_18883701161/article/details/120858261
 

再看 spring.factories 中指定的自动配置过滤器

org.springframework.boot.autoconfigure.AutoConfigurationimportFilter=
org.springframework.boot.autoconfigure.condition.OnBeanCondition,
org.springframework.boot.autoconfigure.condition.OnClassCondition,
org.springframework.boot.autoconfigure.condition.onWebApplicationCondition

都是 XxxCondition 类,检测自动配置类中定义的bean是否满足 @Conditional 系列注解指定的条件

  • OnBeanCondition:校验 @ConditionalOnBean、@ConditionalOnSingleCandidate
  • OnClassCondition:校验 @ConditionalOnClass、@ConditionalOnMissingClass
  • OnWebApplicationCondition:校验 @ConditionalOnWebApplication
     

显然,过滤机制是

通过 @Conditional 系列注解校验自动配置类中定义的bean是否满足条件,满足条件才作为bean放到容器,以提供对应的自动配置,否则不会放到容器中,不提供对应的自动配置。

所谓智能推测可能要使用的自动配置,其实就是通过 @Conditional 系列注解根据web应用类型,classpath中有没有框架、组件的核心类,容器中有没有框架、组件的核心bean来判断应用可能使用了哪些框架、组件,给这些框架、组件提供相应的自动配置。
 

BeanFactory加载bean定义时,自动配置提供的bean总是在自定义的bean之后加载,因为一些 @Conditional 注解要根据容器中的一些自定义bean来检查条件。

 

@AutoConfigurationPackage 自动配置要应用的包
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@import(AutoConfigurationPackages.Registrar.class) //导入 AutoConfigurationPackages 组件
public @interface AutoConfigurationPackage {

	String[] basePackages() default {};

	Class[] basePackageClasses() default {};

}

@AutoConfigurationPackage 用于指定自动配置要应用的包,即对应用中的哪些包、类提供|使用自动配置。

注释提到,没用 basePackages 属性指定要应用的包、类时,默认为此注解所标注的类所在的包。这个注释随着@SpringBootApplication被标注在引导类上,所以默认是对引导类所在的包应用自动配置。

@import 导入的 AutoConfigurationPackages.Registrar 类会把要应用的 basePackages 作为bean注册到容器中。

 

AutoConfigurationimportSelector 自动配置导入选择器

@EnableAutoConfiguration 导入了一个组件

@import(AutoConfigurationimportSelector.class)

AutoConfigurationimportSelector,顾名思义,用于导入 spring.factories 中指定的自动配置类时,对其进行筛选、过滤。

 

AutoConfigurationimportSelector 部分源码

protected List getCandidateConfigurations(Annotationmetadata metadata, AnnotationAttributes attributes) {
	// getSpringFactoriesLoaderFactoryClass() 的值是 EnableAutoConfiguration.class
	List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
			getBeanClassLoader());
	Assert.notEmpty(configurations, "No auto configuration classes found in meta-INF/spring.factories. If you "
			+ "are using a custom packaging, make sure that file is correct.");
	return configurations;
}



protected AutoConfigurationEntry getAutoConfigurationEntry(Annotationmetadata annotationmetadata) {
	if (!isEnabled(annotationmetadata)) {
		return EMPTY_ENTRY;
	}
	
	AnnotationAttributes attributes = getAttributes(annotationmetadata);
	
	//获取 spring.factories 中指定的所有自动配置类
	List configurations = getCandidateConfigurations(annotationmetadata, attributes);
	
	//去掉重复的自动配置类
	configurations = removeDuplicates(configurations);
	
	//根据注解元数据获取 exclude、excludeName 属性的值
	Set exclusions = getExclusions(annotationmetadata, attributes);
	
	//检查 exclude、excludeName 属性设置的值是否有效
	checkExcludedClasses(configurations, exclusions);
	
	//去掉 exclude、excludeName 排除的自动配置类
	configurations.removeAll(exclusions);
	
	//用 spring.factories 中指定的自动配置过滤器对自动配置类进行筛选、过滤
	//留意这个filter(),下面会说到
	configurations = getConfigurationClassFilter().filter(configurations);
	
	//调用 spring.factories 中配置的自动配置导入监听器的回调方法
	//是直接调用监听器中的回调方法,不是以广播器发布事件的形式触发回调
	fireAutoConfigurationimportEvents(configurations, exclusions);
	
	//至此,configurations中的自动配置类都是可能要使用的。
	//封装可能要使用的以及要排除的自动配置类返回
	return new AutoConfigurationEntry(configurations, exclusions);
	
}

 

自动配置导入监听器的日志打印

看上面的 getConfigurationClassFilter().filter(configurations);使用过滤器匹配、校验自动配配置类,部分源码如下

//遍历自动配置过滤器
for (AutoConfigurationimportFilter filter : this.filters) {
	//校验自动配置类中定义的所有bean是否满足当前过滤器的条件
	//关注这个match()
	boolean[] match = filter.match(candidates, this.autoConfigurationmetadata);
	for (int i = 0; i < match.length; i++) {
		if (!match[i]) {
			candidates[i] = null;
			skipped = true;
		}
	}
}

 

match()方法的实现中有一行

//记录 @Conditional 系列注解的匹配|校验结果
report.recordConditionevaluation(autoConfigurationClasses[i], this, outcomes[i]);

100多个自动配置类,匹配信息有六七百行,IO打印很耗时,不会立刻打印,而是暂时保存、记录在内存中,通过监听器 ConditionevaluationReportLoggingListener 来打印。这个监听器会监听ContextRefreshedEvent 事件,上下文刷新后发布上下文已刷新事件,触发监听器回调,打印自动配置类的匹配信息。
 

使用的这个监听器其实就是 spring.factories 指定的那个自动配置导入监听器

# Auto Configuration import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationimportListener=
org.springframework.boot.autoconfigure.condition.ConditionevaluationReportAutoConfigurationimportListener

 

匹配信息默认以debug级别进行打印,debug模式下打印的匹配信息如下

2021-10-19 13:32:28.340  INFO 33444 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path '/mall'

#以下是监听器 ConditionevaluationReportLoggingListener 打印的自动配置类匹配信息(debug级别)
2021-10-19 13:32:28.357 DEBUG 33444 --- [           main] ConditionevaluationReportLoggingListener : 


============================
ConDITIONS evalUATION REPORT
============================


Positive matches:
-----------------

   AopAutoConfiguration matched:
      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)

   AopAutoConfiguration.ClassProxyingConfiguration matched:
      - @ConditionalOnMissingClass did not find unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition)
      - @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)

   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition)
      - found 'session' scope (OnWebApplicationCondition)

	......

 

自动配置原理总结

核心点

@EnableAutoConfiguration + AutoConfigurationimportSelector + spring的factories机制 + @Conditional

 

springboot的自动配置是通过 @EnableAutoConfiguration 注解实现的,这个注解已经包含在了springboot的核心注解 @SpringBootApplication 中。
 

@EnableAutoConfiguration 包含了 @AutoConfigurationPackage 注解

  • 用于指定自动配置要应用的包,默认为所标注的类所属的包,通常是引导类所在的包
     

并用 @import 导入了 AutoConfigurationimportSelector

  • springboot项目都包含了起步依赖 spring-boot-starter,spring-boot-starter 中包含了自动配置 spring-boot-autoconfigure 的依赖。
  • AutoConfigurationimportSelector 会从 spring-boot-autoconfigure 的 meta-INF/spring.factories 中获取指定的自动配置类、自动配置过滤器,去除 exclude、excludeName 排除的自动配置类,通过自动配置过滤器校验自动配置中的 @Conditional 系列注解,满足 @Conditional 的条件说明用到了指定的框架、组件,才把相应的自动配置的bean放到容器中,提供对应的自动配置。
  • 在自动配置过滤器筛选、过滤自动配置类时,会记录匹配信息,保存在内存中,在上下文刷新完成后由 spring.factories 中指定的自动配置导入监听器打印debug级别的匹配信息。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/336500.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号