复制
BeanDefinitionLoader#load方法然后我们回到BeanDefinitionLoader#load
方法 , springboot项目中的bean具体是如何加载的我们在springboot项目的启动调试过程再来分析
int load() {int count = 0;Object[] var2 = this.sources;int var3 = var2.length;for(int var4 = 0; var4 < var3; ++var4) {Object source = var2[var4];// 每加载一个bean来源 , 记录加载数量的count会+1count += this.load(source);}return count;}// 这个加载bean的方法会根据不同的bean来源进行加载 , bean是如何加载的关键就在下面这几个load方法里面private int load(Object source) {Assert.notNull(source, "Source must not be null");if (source instanceof Class) {// 加载配置类中的beanreturn this.load((Class)source);} else if (source instanceof Resource) {// 加载类路径资源中的bean,包括groovy和xml文件中配置的beanreturn this.load((Resource)source);} else if (source instanceof Package) {// 加载包下面的不同配置类中的beanreturn this.load((Package)source);} else if (source instanceof CharSequence) {// 加载根据制定路径的xml文件中配置的beanreturn this.load((CharSequence)source);} else {throw new IllegalArgumentException("Invalid source type " + source.getClass());}}private int load(Class<?> source) {if (this.isGroovyPresent() && BeanDefinitionLoader.GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {BeanDefinitionLoader.GroovyBeanDefinitionSource loader = (BeanDefinitionLoader.GroovyBeanDefinitionSource)BeanUtils.instantiateClass(source, BeanDefinitionLoader.GroovyBeanDefinitionSource.class);this.load(loader);}if (this.isComponent(source)) {this.annotatedReader.register(new Class[]{source});return 1;} else {return 0;}}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");} else {return this.groovyReader.loadBeanDefinitions(source);}} else {return this.xmlReader.loadBeanDefinitions(source);}}private int load(Package source) {return this.scanner.scan(new String[]{source.getName()});}private int load(CharSequence source) {String resolvedSource = this.xmlReader.getEnvironment().resolvePlaceholders(source.toString());try {return this.load(ClassUtils.forName(resolvedSource, (ClassLoader)null));} catch (ClassNotFoundException | IllegalArgumentException var10) {Resource[] resources = this.findResources(resolvedSource);int loadCount = 0;boolean atLeastOneResourceExists = false;Resource[] var6 = resources;int var7 = resources.length;for(int var8 = 0; var8 < var7; ++var8) {Resource resource = var6[var8];if (this.isLoadCandidate(resource)) {atLeastOneResourceExists = true;loadCount += this.load(resource);}}if (atLeastOneResourceExists) {return loadCount;} else {Package packageResource = this.findPackage(resolvedSource);if (packageResource != null) {return this.load(packageResource);} else {throw new IllegalArgumentException("Invalid source '" + resolvedSource + "'");}}}}
复制
刷新Spring应用上下文然后我们回到SpringApplication#run
方法中的this.refreshContext(context);
这行代码 , 并进入方法体
private void refreshContext(ConfigurableApplicationContext context) {// 刷新应用上下文this.refresh(context);if (this.registerShutdownHook) {try {// 如果需要注册关闭钩子 , 则应用上下文注册关闭钩子context.registerShutdownHook();} catch (AccessControlException var3) {}}}protected void refresh(ApplicationContext applicationContext) {Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);((AbstractApplicationContext)applicationContext).refresh();}
复制
AbstractApplicationContext#refresh方法public void refresh() throws BeansException, IllegalStateException {// 刷新应用上下文过程使用了监视器锁synchronized(this.startupShutdownMonitor) {// 预刷新this.prepareRefresh();// 获取刷新beanFactoryConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();// 预备beanFactorythis.prepareBeanFactory(beanFactory);try {// 后置处理beanFactorythis.postProcessBeanFactory(beanFactory);// 执行beanFactory后置处理器this.invokeBeanFactoryPostProcessors(beanFactory);// 注册bean后置处理器this.registerBeanPostProcessors(beanFactory);// 初始化消息源this.initMessageSource();// 初始化应用事件广播this.initApplicationEventMulticaster();// 调用onRefres方法 , 如果是Servlet应用程序 , 这个方法会去创建web服务器this.onRefresh();// 注册监听器this.registerListeners();// 结束beanFactory初始化this.finishBeanFactoryInitialization(beanFactory);// 结束刷新 , 如果是Servlet应用程序 , 个方法会去启动web服务器this.finishRefresh();} catch (BeansException var9) {if (this.logger.isWarnEnabled()) {this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);}// 发生异常时会销毁bean并取消刷新this.destroyBeans();this.cancelRefresh(var9);throw var9;} finally {// finally语句块中重新设置公共缓存this.resetCommonCaches();}}}
经验总结扩展阅读
- 一次SpringBoot版本升级,引发的血案
- 个人办理社保的流程是怎样的 个人怎么交社保
- 回门酒参加的都是谁 回门酒的流程
- 88vip双十一大额消费券领取流程2022 淘宝88vip双十一大额优惠券使用规则
- SpringBoot 03: 常用web组件 - - - 拦截器 + Servlet + 过滤器
- 房屋确权必须是户主吗 房屋确权的办理流程
- 公寓能不能抵押 房产证抵押贷款流程是什么
- SpringBoot 02: 初识SpringBoot
- 二手房网签注意事项 二手房网签流程
- 买房网签之后还有什么流程