SpringBoot自动装配原理解析

       要理解自动装配原理,首先要理解BeanDefinition的作用,在BeanDefinition里定义了一些属性,其实就是将Bean的定义信息存储到这个BeanDefinition相应的属性中,后面对Bean的操作就直接对BeanDefinition进行,例如拿到这个BeanDefinition后,可以根据里面的类名、构造函数、构造函数参数,使用反射进行对象创建,BeanDefinition是一个接口,是一个抽象的定义,实际使用的是其实现类,如 ChildBeanDefinition、RootBeanDefinition、GenericBeanDefinition等。

我们都知道@SpringBootApplication注解里面封装了@ComponentScan注解,这个注解默认情况下扫描main函数所在的包路径,把带有@Component, @Configuration, @Service, @Responsitory的类都加载到Spring 容器中,加载过程是怎么样的呢,在@SpringBootApplication注解上面有@EnableAutoConfiguration注解,在这个注解里面又一个很重要的注解,那就是@Import(AutoConfigurationImportSelector.Class), 这个注解的作用是加载META-INF/spring.factories文件里的内容,spring.factories文件里存储的内容是<key,value> 的键值对,key就是注解或者说配置类(XXXAutoConfiguration,比如@Import这个接口)的全路径,value就是需要自动配置的配置类(上面加上@Configuration的类),拿spring官方的spring-boot-autoconfigure下的spring.properties文件来看一下(部分配置):

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\    # key,下面的都是value
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,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\

 

在AutoConfigurationImportSelector类里面有一个getCandidateConfigurations方法,源码如下:

/**
     * Return the auto-configuration class names that should be considered. By default
     * this method will load candidates using {@link SpringFactoriesLoader} with
     * {@link #getSpringFactoriesLoaderFactoryClass()}.
     * @param metadata the source metadata
     * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
     * attributes}
     * @return a list of candidate configurations
     */
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        List<String> 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;
    }
 

我们进入loadFactoryNames方法查看:

public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();
        return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
    }

    private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
        MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {
            try {
                Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
                LinkedMultiValueMap result = new LinkedMultiValueMap();

                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();

                    while(var6.hasNext()) {
                        Entry<?, ?> entry = (Entry)var6.next();
                        String factoryClassName = ((String)entry.getKey()).trim();
                        String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                        int var10 = var9.length;

                        for(int var11 = 0; var11 < var10; ++var11) {
                            String factoryName = var9[var11];
                            result.add(factoryClassName, factoryName.trim());
                        }
                    }
                }

                cache.put(classLoader, result);
                return result;
            } catch (IOException var13) {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
            }
        }
    }

看到classLoader.getResources了吧,它会去找META-INF/spring.factories文件,加载进来,解析文件的内容,根据键值对对应关系,循环遍历spring.factories,把每个键值对解析为一个.property文件,然后再放到一个beanDefinitionMap里面,这个map的key是beanName,value是beanDefinition对象,有了这个beanDefinitionMap,spring会遍历这个map,对每个bean进行实例化(懒加载的除外),这样就得到了autoConfiguration里面每个bean的实例,可以对其进行属性的配置

 

 

标签: spring

好文要顶 关注我 收藏该文  

成功没有捷径
关注 - 0
粉丝 - 0

0

0

« 上一篇: 股票买到手想卖可以随时都能卖掉吗

posted on 2019-11-30 19:18  成功没有捷径  阅读(0)  评论(0)  编辑 收藏

刷新评论刷新页面返回顶部

发表评论

昵称:

评论内容:

引用 粗体 链接 缩进 代码 图片

 

 退出

[Ctrl+Enter快捷键提交]

【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
【推荐】腾讯云海外1核2G云服务器低至2折,半价续费券限量免费领取!
【推荐】阿里云双11返场来袭,热门产品低至一折等你来抢!
【推荐】天翼云双十一翼降到底,云主机11.11元起,抽奖送大礼
【推荐】流程自动化专家UiBot,体系化教程成就高薪RPA工程师
【活动】京东云服务器_云主机低于1折,低价高性能产品备战双11
【优惠】七牛云采购嘉年华,云存储、CDN等云产品低至1折

 

相关博文:
· SpringBoot自动装配原理解析
· SpringBoot自动装配原理
· SpringBoot自动装配源码解析
· SpringBoot自动装配的原理
· SpringBoot自动装配原理分析
» 更多推荐...

阿里技术3年大合辑免费电子书一键下载

 

最新 IT 新闻
· Infor转型十年启示录:ERP套件厂商为什么要做云平台? 
· 开拓创新十余年,中国移动IPv6项目获中国通信学会一等奖 
· 微软官宣,打开华为PC爆发式洪流之闸 
· 小米再次回购股份:4亿港元回购约4483万股 
· 拥抱云端,计算未来 
» 更多新闻...

昵称: 成功没有捷径 
园龄: 1年11个月 
粉丝: 
关注: 0

<2019年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

 

搜索

 

 

常用链接

我的标签

随笔分类

随笔档案

文章分类

阅读排行榜

Powered by: 博客园 模板提供:沪江博客 Copyright © 2019 成功没有捷径 
Powered by .NET Core 3.0.0 on Linux

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Micrle_007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值