Spring boot源码分析-BeanDefinitionLoader(7)

Spring boot源码分析-BeanDefinitionLoader(7)

BeanDefinitionLoader用来注册xml或者javaConfig中的bean,是AnnotatedBeanDefinitionReader的一个简单的外观模式,主要做的工作就是注册bean
该类在Springboot主函数准备Context容器的prepareContext的方法中被调用

private void prepareContext(ConfigurableApplicationContext context,
                                ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
                                ApplicationArguments applicationArguments, Banner printedBanner) {
        context.setEnvironment(environment);
        //设置获取
        postProcessApplicationContext(context);
        //对context进行initializer操作
        applyInitializers(context);
        //在springboot初始化的时候 没有针对context的Prepared做任何的操作
        listeners.contextPrepared(context);
        if (this.logStartupInfo) {
            logStartupInfo(context.getParent() == null);
            logStartupProfileInfo(context);
        }

        // Add boot specific singleton beans
        // DefaultListableBeanFactory
        // 注册springApplicationArguments的bean 用来存放启动时候的Arguments
        context.getBeanFactory().registerSingleton("springApplicationArguments",
                applicationArguments);
        if (printedBanner != null) {
            context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
        }

        // Load the sources
        // 获取启动参数里面的sources 一般就是Configuration的配置类
        Set<Object> sources = getSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        //load就是加载配置的类
        load(context, sources.toArray(new Object[sources.size()]));
        //容器准备完成 还没有调reflash方法的时候,主要可以对容器设置context.addBeanFactoryPostProcessor(),用于对BeanFactory进行一些设置
        listeners.contextLoaded(context);
    }
  • 首先看这个BeanDefinitionLoader的成员变量,BeanDefinitionLoader持有了各种类型的BeanDefinitionReader,都是用来注册bean用的
class BeanDefinitionLoader {
    private final Object[] sources;
    private final AnnotatedBeanDefinitionReader annotatedReader;
    private final XmlBeanDefinitionReader xmlReader;
    private BeanDefinitionReader groovyReader;
    private final ClassPathBeanDefinitionScanner scanner;
    private ResourceLoader resourceLoader;

    }

可以根据各种传入的参数处理,注册bean,有一下三种情况:

1.处理javaConfig,当传入的是一个ChapterProfilesApplication.class的bean的时候,会使用AnnotatedBeanDefinitionReader去处理参数

    SpringApplication.run(ChapterProfilesApplication.class, args);
    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);
            }
        }
        if (isComponent(source)) {
            this.annotatedReader.register(source);
            return 1;
        }
        return 0;
    }

2.处理Package,当传入的是一个Package的bean的时候,会使用ClassPathBeanDefinitionScanner去处理参数

        Package aPackage =Package.getPackage("com.leone.chapter.profiles");
        SpringApplication.run(aPackage, args);
    private int load(Package source) {
        return this.scanner.scan(source.getName());
    }

3.处理Resource类型的配置,会使用XmlBeanDefinitionReader去处理注册bean

        SpringApplication.run(new ClassPathResource("applicationContext.xml"), args);
    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);
        }
        return this.xmlReader.loadBeanDefinitions(source);
    }

4.处理String类型的配置,会按照class,Resource,Package的顺序尝试去解析String串进行加载

SpringApplication.run("classpath:/applicationContext.xml", args);
private int load(CharSequence source) {
        String resolvedSource = this.xmlReader.getEnvironment()
                .resolvePlaceholders(source.toString());
        // Attempt as a Class
        try {
            return load(ClassUtils.forName(resolvedSource, null));
        }
        catch (IllegalArgumentException ex) {
            // swallow exception and continue
        }
        catch (ClassNotFoundException ex) {
            // swallow exception and continue
        }
        // Attempt as resources
        Resource[] resources = findResources(resolvedSource);
        int loadCount = 0;
        boolean atLeastOneResourceExists = false;
        for (Resource resource : resources) {
            if (isLoadCandidate(resource)) {
                atLeastOneResourceExists = true;
                loadCount += load(resource);
            }
        }
        if (atLeastOneResourceExists) {
            return loadCount;
        }
        // Attempt as package
        Package packageResource = findPackage(resolvedSource);
        if (packageResource != null) {
            return load(packageResource);
        }
        throw new IllegalArgumentException("Invalid source '" + resolvedSource + "'");
    }
    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/jamet/article/details/78291900
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞