(四)SpringBoot启动过程的分析-预处理ApplicationContext (3)

将参数对象注册为单例模式

// SpringApplication.java ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments", applicationArguments); 是否允许覆盖Bean定义

这个是和spring.main.allow-bean-definition-overriding参数有关,默认情况下在DefaultListableBeanFactory中是true,但是SpringBoot在此处给设置成了false。

if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } 加载Bean到上下文中

加载需要两个必备条件:谁来加载Bean,从哪加载Bean;此处加载BeanDefinition是由BeanDefinitionLoader来完成。

// SpringApplication.java#prepareContext() // 获取当前应用要加载的资源 Set<Object> sources = getAllSources(); Assert.notEmpty(sources, "Sources must not be empty"); // 加载Bean load(context, sources.toArray(new Object[0])); // 创建Bean加载器,并加载 protected void load(ApplicationContext context, Object[] sources) { if (logger.isDebugEnabled()) { logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources)); } // 创建BeanDefinitionLoader BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources); if (this.beanNameGenerator != null) { loader.setBeanNameGenerator(this.beanNameGenerator); } if (this.resourceLoader != null) { loader.setResourceLoader(this.resourceLoader); } if (this.environment != null) { loader.setEnvironment(this.environment); } loader.load(); } 初始化BeanDefinitionLoader

用于创建BeanDefinitionLoader,并从source加载类,它是对加载Bean的整体功能做了封装,内部由不同的资源加载类来完成不同类型的资源加载,例如从基于注解的类来开始加载,从xml文件开始加载

// SpringApplication.java protected BeanDefinitionLoader createBeanDefinitionLoader(BeanDefinitionRegistry registry, Object[] sources) { return new BeanDefinitionLoader(registry, sources); } class BeanDefinitionLoader { // 类的来源 private final Object[] sources; // JavaConfig类读取器 private final AnnotatedBeanDefinitionReader annotatedReader; // xml文件类读取器 private final XmlBeanDefinitionReader xmlReader; // groovy类读取器 private BeanDefinitionReader groovyReader; // classpath类读取器 private final ClassPathBeanDefinitionScanner scanner; // 资源加载器 private ResourceLoader resourceLoader; BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) { Assert.notNull(registry, "Registry must not be null"); Assert.notEmpty(sources, "Sources must not be empty"); this.sources = sources; this.annotatedReader = new AnnotatedBeanDefinitionReader(registry); this.xmlReader = new XmlBeanDefinitionReader(registry); if (isGroovyPresent()) { this.groovyReader = new GroovyBeanDefinitionReader(registry); } this.scanner = new ClassPathBeanDefinitionScanner(registry); this.scanner.addExcludeFilter(new ClassExcludeFilter(sources)); } // ...省略部分代码 }

通过观察它的内部属性和构造方法可以看出,它支持加载基于编程方式配置的类,支持xml文件配置的类,支持groovy和xml混合定义的类的加载。它使用门面模式封装了这些具体的加载器。此处只需要先知道BeanDefinitionLoader用于加载Bean,且它内部封装了多个类读取器即可
不必深入。先了解大体的功能性即可。后续会开单独篇章介绍。

使用BeanDefinitionLoader加载Bean // BeanDefinitionLoader.java // ① 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()); }

① - 记录加载的资源数量
② - 根据传入的资源类型选择不同的加载方式

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyjyf.html