Spring Boot源码简析(二)

Spring Boot源码简析(二)

load 资源过程

在上一篇博客中我们说了SpringApplication的主要启动逻辑,其中context创建之后第一步就是执行

load(context, sources.toArray(new Object[sources.size()]));

load主要就是把我们传入的资源生成相应的BeanDefinition。

protected void load(ApplicationContext context, Object[] sources) {
    //创建一个BeanDefinitionLoader,看名字就知道使用来加载Bean信息的
    BeanDefinitionLoader loader = createBeanDefinitionLoader(
            getBeanDefinitionRegistry(context), sources);
            //塞一个beanNameGenerator
    if (this.beanNameGenerator != null) {
        loader.setBeanNameGenerator(this.beanNameGenerator);
    }
    //塞一个resourceLoader,用来先加载资源然后再解析
    if (this.resourceLoader != null) {
        loader.setResourceLoader(this.resourceLoader);
    }
    if (this.environment != null) {
        loader.setEnvironment(this.environment);
    }
    //开始加载
    loader.load();
}

这里主要是先创建了一个BeanDefinitionLoader并在加载前做了一些准备工作,然后执行加载操作。

public int load() {
    int count = 0;
    for (Object source : this.sources) {
        count += load(source);
    }
    return count;
}

private int load(Object source) {
    Assert.notNull(source, "Source must not be null");
    if (source instanceof Class<?>) {
        return load((Class<?>) source);
    }
    if (source instanceof Resource) {
        return load((Resource) source);
    }
    if (source instanceof Package) {
        return load((Package) source);
    }
    if (source instanceof CharSequence) {
        return load((CharSequence) source);
    }
    throw new IllegalArgumentException("Invalid source type " + source.getClass());
}

此处是根据传入的资源类型来加载资源,下面根据具体的资源类型来查看资源加载资源

Load class

private int load(Class<?> source) {
    if (isGroovyPresent()) {
        // Any GroovyLoaders added in beans{} DSL can contribute beans here
        if (GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
            GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,
                    GroovyBeanDefinitionSource.class);
            load(loader);
        }
    }
    //查看元素是否有@Component注解
    if (isComponent(source)) {
    //将source对应的类型注册一个beanDefinition
        this.annotatedReader.register(source);
        return 1;
    }
    return 0;
}

这里就是将我们传入的类创建对应的beanDefinition并注册到registry中去。
Load resource

private int load(Resource source) {
    if (source.getFilename().endsWith(".groovy")) {
        if (this.groovyReader == null) {
            throw new BeanDefinitionStoreException(
                    "Cannot load Groovy beans without Groovy on classpath");
        }
        return this.groovyReader.loadBeanDefinitions(source);
    }
    //调用xmlReader来加载beanDefinition
    return this.xmlReader.loadBeanDefinitions(source);
}

这里可以很明显看到,通过资源加载其实也就是我们平时使用xml配置,springboot是可以支持像spring一样的通过配置文件配置bean的方式。

Load package

private int load(Package source) {
    //调用扫描器来扫描package下所有类文件
    return this.scanner.scan(source.getName());
}

这里是我比较感兴趣的地方,因为在spring没有配置文件的情况下,主要的bean加载的方式就应该是通过这个方法实现

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {

    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
    //遍历所有的包
    for (String basePackage : basePackages) {
        Set<BeanDefinition> candidates =
        //扫描该包下的所有文件,包含componet注解的类将会创建对应的BeanDefinition
        findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            //获取bean的scope信息,主要是是否是singleton、是否需要代理
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            //创建beanName
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            if (candidate instanceof AbstractBeanDefinition) {
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            if (checkCandidate(beanName, candidate)) {
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

总体来说,load的操作就是把用户传入的各种资源对应的bean的beanDefinition信息到注册中心。

    原文作者:Spring Cloud
    原文地址: https://blog.csdn.net/feiyingHiei/article/details/79133321
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞