美文网首页
springboot如何自动装配

springboot如何自动装配

作者: 毛于晏 | 来源:发表于2020-11-16 10:58 被阅读0次

    1.启动装配入口

    XxxxApplication

    package com.example.springboot;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    //关键注解, 自动注入的关键
    @SpringBootApplication
    public class SpringbootApplication {
    
    
        public static void main(String[] args) {
            //run方法, springboot启动入口, 解释注解, 加载配置
            SpringApplication.run(SpringbootApplication.class, args);
        }
    
    }
    

    2.@SpringBootApplication

    @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 {
    //.........省略内容
    }
    
    

    3.@EnableAutoConfiguration

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage    
    @Import(AutoConfigurationImportSelector.class)    //关键注解, 导入AutoConfigurationImportSelector类, 该类中关键方法org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports
    public @interface EnableAutoConfiguration {
    //.........省略内容
    }
    

    4.org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports

    @Override
        public String[] selectImports(AnnotationMetadata annotationMetadata) {
            if (!isEnabled(annotationMetadata)) {
                return NO_IMPORTS;
            }
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                    .loadMetadata(this.beanClassLoader);
              //自动注入的Entry
            AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
                    autoConfigurationMetadata, annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    

    org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations
    -->
    org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames
    -->
    org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories

    private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
            MultiValueMap<String, String> result = cache.get(classLoader);
            if (result != null) {
                return result;
            }
    
            try {
                //加载自动装配类所处位置FACTORIES_RESOURCE_LOCATION  --> META-INF/spring.factories
                Enumeration<URL> urls = (classLoader != null ?
                        classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                        ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
                result = new LinkedMultiValueMap<>();
                while (urls.hasMoreElements()) {
                    URL url = urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    for (Map.Entry<?, ?> entry : properties.entrySet()) {
                        String factoryClassName = ((String) entry.getKey()).trim();
                        for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
                            result.add(factoryClassName, factoryName.trim());
                        }
                    }
                }
                cache.put(classLoader, result);
                return result;
            }
            catch (IOException ex) {
                throw new IllegalArgumentException("Unable to load factories from location [" +
                        FACTORIES_RESOURCE_LOCATION + "]", ex);
            }
        }
    

    5.META-INF/spring.factories

    自动装配的类全名

    # 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.CloudServiceConnectorsAutoConfiguration,\
    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
    org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
    

    6.不是所有spring.factories的类都加载

    例如:

    @Configuration
    //@ConditionalOnClass 存在这些类才加载, 否则不加载, 没有加入依赖, 以下类都是未导入的
    @ConditionalOnClass({ MongoClient.class, com.mongodb.client.MongoClient.class,
            MongoTemplate.class })
    @Conditional(AnyMongoClientAvailable.class)
    @EnableConfigurationProperties(MongoProperties.class)
    @Import(MongoDataConfiguration.class)
    @AutoConfigureAfter(MongoAutoConfiguration.class)
    public class MongoDataAutoConfiguration {
    
        private final MongoProperties properties;
    
        public MongoDataAutoConfiguration(MongoProperties properties) {
            this.properties = properties;
        }
    
        @Bean
        @ConditionalOnMissingBean(MongoDbFactory.class)
        public MongoDbFactorySupport<?> mongoDbFactory(ObjectProvider<MongoClient> mongo,
                ObjectProvider<com.mongodb.client.MongoClient> mongoClient) {
            MongoClient preferredClient = mongo.getIfAvailable();
            if (preferredClient != null) {
                return new SimpleMongoDbFactory(preferredClient,
                        this.properties.getMongoClientDatabase());
            }
            com.mongodb.client.MongoClient fallbackClient = mongoClient.getIfAvailable();
            if (fallbackClient != null) {
                return new SimpleMongoClientDbFactory(fallbackClient,
                        this.properties.getMongoClientDatabase());
            }
            throw new IllegalStateException("Expected to find at least one MongoDB client.");
        }
    //......省略内容
    

    相关文章

      网友评论

          本文标题:springboot如何自动装配

          本文链接:https://www.haomeiwen.com/subject/cayabktx.html