大家好,我是程序员田同学
上篇文章对spring外围启动办法refresh做了整体的解读,然而只是泛泛而谈,接下来会出一零碎文章对每个办法的源码进行粗浅解读。
第一篇文章见 spring源码之办法概览
首先,第一个办法是prepareRefresh()办法,这个办法做的事很简略,也不是本文的重点。该办法记录容器的启动工夫,初始化监听容器。
protected void prepareRefresh() { // Switch to active //纪录启动工夫 this.startupDate = System.currentTimeMillis(); System.out.println("spring启动工夫为--------------------" + this.startupDate); this.closed.set(false); System.out.println("spring标记为未敞开--------------------" + this.closed); this.active.set(true); System.out.println("spring以后激活状态--------------------" + this.active); if (logger.isDebugEnabled()) { if (logger.isTraceEnabled()) { logger.trace("Refreshing " + this); } else { logger.debug("Refreshing " + getDisplayName()); } } // Initialize any placeholder property sources in the context environment. //空办法 initPropertySources(); // Validate that all properties marked as required are resolvable: // see ConfigurablePropertyResolver#setRequiredProperties //校验 xml配置文件 getEnvironment().validateRequiredProperties(); // Store pre-refresh ApplicationListeners... //初始化applicationListeners监听容器 if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<> (this.applicationListeners); } else { // Reset local application listeners to pre-refresh state. this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... this.earlyApplicationEvents = new LinkedHashSet<>(); }
读者大抵搂一眼即可,对这个办法整体就能很快把握。
接下来才是明天的重头戏——obtainFreshBeanFactory()办法,是refresh()办法中的第二个办法,也是整个refresh()办法中外围办法之一。
该办法次要的作用是,这里将会初始化 BeanFactory、加载 Bean、注册 Bean 等等。(Bean 并没有实现初始化)
点进去obtainFreshBeanFactory()办法咱们一探到底。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 敞开旧的 BeanFactory (如果有),创立新的 BeanFactory,加载 Bean 定义、注册 Bean 等等 refreshBeanFactory(); // 返回刚刚创立的 BeanFactory ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory;}
refreshBeanFactory()应该是这个办法的重头戏,咱们再深刻进去。
@Overrideprotected final void refreshBeanFactory() throws BeansException { // 如果 ApplicationContext 中曾经加载过 BeanFactory 了,销毁所有 Bean,敞开 BeanFactory // 留神,利用中 BeanFactory 原本就是能够多个的,这里可不是说利用全局是否有 BeanFactory,而是以后ApplicationContext 是否有 BeanFactory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // 初始化一个 DefaultListableBeanFactory,为什么应用这个BeanFactory?因为这是最牛的 BeanFactory。 DefaultListableBeanFactory beanFactory = createBeanFactory(); // 用于 BeanFactory 的序列化 beanFactory.setSerializationId(getId()); // 设置 BeanFactory 的两个配置属性:是否容许 Bean 笼罩、是否容许循环援用 customizeBeanFactory(beanFactory); // 加载 Bean 到 BeanFactory 中 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); }}
简略提一句,DefaultListableBeanFactory为什么是最牛的BeanFactory看下这个继承图大略就明了。
// 设置 BeanFactory 的两个配置属性:是否容许 Bean 笼罩、是否容许循环援用 customizeBeanFactory(beanFactory);
这个形式只是一个设置,设置是否容许循环依赖,至于什么是循环依赖呢?也就是 A-B-C之间他们相互依赖,spring有一套本人的机制去解决循环依赖,当前文章为进行剖析,这一步仅仅是配置是否容许循环依赖,读者分明就能够了。
// 这个办法将依据配置,加载各个 Bean,而后放到 BeanFactory 中 loadBeanDefinitions(beanFactory);
通过下面一系列的步骤,一个beandefintion就造成,beandefintion就是咱们常说的bean,也就是一个对象的加强版。
接下来就须要把这个bean退出到beanfactory中了,这一步交给loadBeanDefinitions()办法去执行。
spring办法命名的确精妙,只看看办法名大略也晓得每个办法干了什么!
创立一个beanDefinitionReader(bean阅读器)去读取xml中的bean,尽管xml很少用了,然而用它来举例还是很经典的。
真正干活的是loadBeanDefinitions(beanDefinitionReader),往下走很漫长漫长,把咱们xml中的bean解析成BeanDefinition,并调用registerBeanDefinition()办法把它注册到注册核心,发送注册事件。
总结一下,到这里曾经初始化了 Bean 容器,<bean />
配置也相应的转换为了一个个 BeanDefinition,而后注册了各个 BeanDefinition 到注册核心,并且发送了注册事件。
到此obtainFreshBeanFactory() 办法也就正式完结了。
spring的调用过程链路十分十分的长,一步步点进去没一会你就迷了,田同学认为比拟好的一个方法就是,先站在办法体外看这个办法干了什么,而后逐渐拆分进入到每一个办法中。
站在refresh()外看这两个办法,prepareRefresh()筹备一下刷新要做的事,obtainFreshBeanFactory()注册好bean并退出到beanfactory中。
好啦,明天的spring源码剖析就到这里了。