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

SpringBoot自动装配原理分析

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

SpringBoot自动装配原理分析

SpringBoot能流行起来我觉得有个重要的原因就是它的自动装配,想想使用SpringBoot与Spring开发项目的区别,第一反应就是减少了很多配置。

其实SpringBoot是基于Spring基础之上的,通过MAVEN引入SpringBoot也会发现,它传递依赖了Spring。所以配置并没有减少,只是它帮我们自动配置了,这些自动配置的类都在spring-boot-autoconfigure-版本.jar包中。

以一个最简单的SpringBoot应用为例,通常需要写这样一个启动类:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {
    
    public static void main(String[] args) {
 SpringApplication springApplication = new SpringApplication(Application.class);
 springApplication.setBannerMode(Banner.Mode.LOG);
 springApplication.run(args);
    }
    
}

进入@SpringBootApplication注解内部,可以看到与自动装配有关的@EnableAutoConfiguration:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
 @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
 @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    // ...
}

@EnableAutoConfiguration通过@import方式引入了EnableAutoConfigurationimportSelector:

@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@AutoConfigurationPackage
@import(EnableAutoConfigurationimportSelector.class)
public @interface EnableAutoConfiguration {
    // ...
}

EnableAutoConfigurationimportSelector是一个importSelector,我们查看其selectimports方法,其内部调用getCandidateConfigurations方法,读取meta-INF/spring.factories里配置的Configuration类。

@Override
public String[] selectimports(Annotationmetadata annotationmetadata) {
    if (!isEnabled(annotationmetadata)) {
 return NO_importS;
    }
    try {
 AutoConfigurationmetadata autoConfigurationmetadata = AutoConfigurationmetadataLoader.loadmetadata(this.beanClassLoader);
 AnnotationAttributes attributes = getAttributes(annotationmetadata);
 List configurations = getCandidateConfigurations(annotationmetadata, attributes); // meta-INF/spring.factories
 configurations = removeDuplicates(configurations);
 configurations = sort(configurations, autoConfigurationmetadata);
 Set exclusions = getExclusions(annotationmetadata, attributes);
 checkExcludedClasses(configurations, exclusions);
 configurations.removeAll(exclusions);
 configurations = filter(configurations, autoConfigurationmetadata);
 fireAutoConfigurationimportEvents(configurations, exclusions);
 return configurations.toArray(new String[configurations.size()]);
    }
    catch (IOException ex) {
 throw new IllegalStateException(ex);
    }
}

在SpringBoot的spring-boot-autoconfigure-版本.jar包中,spring.factories文件里预定义了很多Configuration类:

# Initializers
org.springframework.context.ApplicationContextInitializer=
org.springframework.boot.autoconfigure.SharedmetadataReaderFactoryContextInitializer,
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer

# Application Listeners
org.springframework.context.ApplicationListener=
org.springframework.boot.autoconfigure.BackgroundPreinitializer

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

# Auto Configuration import Filters
org.springframework.boot.autoconfigure.AutoConfigurationimportFilter=
org.springframework.boot.autoconfigure.condition.OnClassCondition

# Auto Configure
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.cloud.CloudAutoConfiguration,
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,
......

到这里自动装配的主流程就结束了,然后具体的装配逻辑就在各自的Configuration类中。

以常见的HttpEncodingAutoConfiguration为例,这些Configuration类都添加了@Configuration注解表名都是配置类,然后通过例如:@ConditionalXXX等判断通过代码方式创建需要用到的Bean。

@Configuration
@EnableConfigurationProperties(HttpEncodingProperties.class)
@ConditionalOnWebApplication
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

    private final HttpEncodingProperties properties;

    public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
 this.properties = properties;
    }

    @Bean
    @ConditionalOnMissingBean(CharacterEncodingFilter.class)
    public CharacterEncodingFilter characterEncodingFilter() {
 CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
 filter.setEncoding(this.properties.getCharset().name());
 filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
 filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
 return filter;
    }

    @Bean
    public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
 return new LocaleCharsetMappingsCustomizer(this.properties);
    }

    private static class LocaleCharsetMappingsCustomizer implements EmbeddedServletContainerCustomizer, Ordered {
 
 private final HttpEncodingProperties properties;
 
 LocaleCharsetMappingsCustomizer(HttpEncodingProperties properties) {
     this.properties = properties;
 }

 @Override
 public void customize(ConfigurableEmbeddedServletContainer container) {
     if (this.properties.getMapping() != null) {
  container.setLocaleCharsetMappings(this.properties.getMapping());
     }
 }

 @Override
 public int getOrder() {
     return 0;
 }

    }
    
}
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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