Spring boot源码分析-BeanDefinitionLoader(7)

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

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 + "'");
        }

来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring boot源码分析-BeanDefinitionLoader(7)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏