Spring IOC容器在初始化以后会对容器中非懒加载的,单例的以及非抽象的bean定义进行bean的初始化操做,同时会也涉及到Bean的后置处理器以及DI(依赖注入)等行为。对于Bean的初始化,Spring是经过第一次调用getBean方法向容器获取bean实例时进行的。下面的源码分析也是基于getBean()做为入口一步步去了解Spring是如何初始化单例Bean的。segmentfault
咱们知道Spring IOC容器初始化后会对容器中非懒加载的,单例的以及非抽象的bean定义进行bean的初始化操做,因此咱们分析源码的入口也就是在容器初始化的入口,分析容器初始化后Spring在什么地方开始第一次的Bean初始化。缓存
在以前的一篇博文Spring专题之IOC源码分析中有分析到Spring IOC容器初始化的过程,过程源码以下:session
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从 //子类的refreshBeanFactory()方法启动 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. //为BeanFactory配置容器特性,例如类加载器、事件处理器等 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. //为容器的某些子类指定特殊的BeanPost事件处理器 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //调用全部注册的BeanFactoryPostProcessor的Bean invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //为BeanFactory注册BeanPost事件处理器. //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. //初始化信息源,和国际化相关. initMessageSource(); // Initialize event multicaster for this context. //初始化容器事件传播器. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. //调用子类的某些特殊Bean初始化方法 onRefresh(); // Check for listener beans and register them. //为事件传播器注册事件监听器. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //初始化全部剩余的单例Bean finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. //初始化容器的生命周期事件处理器,并发布容器的生命周期事件 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. //销毁已建立的Bean destroyBeans(); // Reset 'active' flag. //取消refresh操做,重置容器的同步标识. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
上述源码能够观察看在IOC容器被初始化后进行了不少其余的操做,但这些如今咱们暂时不关心,咱们须要关注的只有finishBeanFactoryInitialization这个方法,这个方法的做用就是初始化全部剩余的单例Bean,因此这也是咱们如下分析源码的入口。并发
finishBeanFactoryInitialization方法源码以下:app
//对配置了lazy-init属性的Bean进行预实例化处init属性的Bean进行预实例化处理理 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { .... // Instantiate all remaining (non-lazy-init) singletons. //对配置了lazy-init属性的单态模式Bean进行预实例化处理 beanFactory.preInstantiateSingletons(); }
这个方法前面一些处理暂时不看,能够知道最后调用了ConfigurableListableBeanFactory的preInstantiateSingletons方法,也就是对配置了lazy-init属性的单态模式Bean进行预实例化处理。
下面进入preInstantiateSingletons方法分析,源码以下:源码分析
//对配置lazy-init属性单态Bean的预实例化 public void preInstantiateSingletons() throws BeansException { if (this.logger.isDebugEnabled()) { this.logger.debug("Pre-instantiating singletons in " + this); } List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); for (String beanName : beanNames) { //获取指定名称的Bean定义 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //Bean不是抽象的,是单态模式的,且lazy-init属性配置为false if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { //若是指定名称的bean是建立容器的Bean if (isFactoryBean(beanName)) { //FACTORY_BEAN_PREFIX=”&”,当Bean名称前面加”&”符号 //时,获取的是产生容器对象自己,而不是容器产生的Bean. //调用getBean方法,触发容器对Bean实例化和依赖注入过程 final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); //标识是否须要预实例化 boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { //一个匿名内部类 isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> ((SmartFactoryBean<?>) factory).isEagerInit(), getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { //调用getBean方法,触发容器对Bean实例化和依赖注入过程 getBean(beanName); } } else { //调用getBean方法,触发容器对Bean实例化和依赖注入过程 getBean(beanName); } } } //触发bean初始化后的回调 ... }
经过源码解析,咱们能够看到这里对于不是抽象的,是单态模式的,且lazy-init属性配置为false的Bean定义进行初始化,而初始化过程正是调用了getBean方法。下面咱们进入getBean方法观察Spring对bean的初始化过程。getBean方法及相关调用源码以下:post
//获取IOC容器中指定名称的Bean public Object getBean(String name) throws BeansException { //doGetBean才是真正向IoC容器获取被管理Bean的过程 return doGetBean(name, null, null, false); } //真正实现向IOC容器获取Bean的功能,也是触发依赖注入功能的地方 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { //根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖,若是指定的是别名,将别名转换为规范的Bean名称 final String beanName = transformedBeanName(name); Object bean; //先从缓存中取是否已经有被建立过的单态类型的Bean,对于单例模式的Bean整个IOC容器中只建立一次,不须要重复建立 Object sharedInstance = getSingleton(beanName); //IOC容器建立单例模式Bean实例对象 if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { //若是指定名称的Bean在容器中已有单例模式的Bean被建立 //直接返回已经建立的Bean if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } //获取给定Bean的实例对象,主要是完成FactoryBean的相关处理。注意:BeanFactory是管理容器中Bean的工厂,而FactoryBean是建立建立对象的工厂Bean,二者之间有区别 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { //缓存没有正在建立的单例模式Bean,缓存中已经有已经建立的原型模式Bean,可是因为循环引用的问题致使实例化对象失败 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } //对IOC容器中是否存在指定名称的BeanDefinition进行检查,首先检查是否能在当前的BeanFactory中获取的所须要的Bean,若是不能则委托当前容器的父级容器去查找,若是仍是找不到则沿着容器的继承体系向父级容器查找 BeanFactory parentBeanFactory = getParentBeanFactory(); //当前容器的父级容器存在,且当前容器中不存在指定名称的Bean if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { //解析指定Bean名称的原始名称 String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { //委派父级容器根据指定名称和显式的参数查找 return (T) parentBeanFactory.getBean(nameToLookup, args); } else { //委派父级容器根据指定名称和类型查找 return parentBeanFactory.getBean(nameToLookup, requiredType); } } //建立的Bean是否须要进行类型验证,通常不须要 if (!typeCheckOnly) { //向容器标记指定的Bean已经被建立 markBeanAsCreated(beanName); } try { //根据指定Bean名称获取其父级的Bean定义 //主要解决Bean继承时子类合并父类公共属性问题 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); //获取当前Bean全部依赖Bean的名称 String[] dependsOn = mbd.getDependsOn(); //若是当前Bean有依赖Bean if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } //递归调用getBean方法,获取当前Bean的依赖Bean registerDependentBean(dep, beanName); //把被依赖Bean注册给当前依赖的Bean getBean(dep); } } //建立单例模式Bean的实例对象 if (mbd.isSingleton()) { //这里使用了一个匿名内部类,建立Bean实例对象,而且注册给所依赖的对象 sharedInstance = getSingleton(beanName, () -> { try { //建立一个指定Bean实例对象,若是有父级继承,则合并子类和父类的定义 return createBean(beanName, mbd, args); } catch (BeansException ex) { //显式地从容器单例模式Bean缓存中清除实例对象 destroySingleton(beanName); throw ex; } }); //获取给定Bean的实例对象 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } //IOC容器建立原型模式Bean实例对象 else if (mbd.isPrototype()) { //原型模式(Prototype)是每次都会建立一个新的对象 Object prototypeInstance = null; try { //回调beforePrototypeCreation方法,默认的功能是注册当前建立的原型对象 beforePrototypeCreation(beanName); //建立指定Bean对象实例 prototypeInstance = createBean(beanName, mbd, args); } finally { //回调afterPrototypeCreation方法,默认的功能告诉IOC容器指定Bean的原型对象再也不建立 afterPrototypeCreation(beanName); } //获取给定Bean的实例对象 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } //要建立的Bean既不是单例模式,也不是原型模式,则根据Bean定义资源中配置的生命周期范围,选择实例化Bean的合适方法,这种在Web应用程序中,比较经常使用,如:request、session、application等生命周期 else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); //Bean定义资源中没有配置生命周期范围,则Bean定义不合法 if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { //这里又使用了一个匿名内部类,获取一个指定生命周期范围的实例 Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); //获取给定Bean的实例对象 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { ... } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } //对建立的Bean实例对象进行类型检查 if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { ... } } return (T) bean; }
这里经过上述源码的分析,总结如下Spring初始化bean的过程,首先Spring会去缓存中搜索是否已存在bean实例,若是存在则直接取出返回,不存在就判断是否存在父容器,存在则调用父容器的getBean方法进行初始化,不然经过判断bean定义是不是单例bean,是不是原型bena进行相关的初始化操做,能够知道最后都是调用了createBean方法去建立bean的。ui
至此,经过上述的源码分析,咱们对Spring在IOC初始化后对bean的初始化过程有了大体的了解,下篇博客会继续这篇经过源码分析Spring初始化的具体过程。this