Spring源码解析之Bean的加载
2017-01-02 20:25
309 查看
本文基于Spring4.2.7版本,由于Bean的处理是Spring的核心模块,所以版本之间也没有太大的差异
从源码中看端倪
相信大家多少有些基本的概念了,我们就从源码中来看看Spring是如何加载Bean的。java // 从IOC容器中获取bean的基本方法 // 了解Spring的同学应该知道,getXXX往往是预处理,doGetXXX才是真正的获取 @SuppressWarnings("unchecked") protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { // 如果是bean的别名或者bean的工厂名都会在这里处理掉 // bean的工厂名(bean名称前加&符号)也是Spring用于防止循环依赖和松耦合的创新方法 final String beanName = transformedBeanName(name); Object bean; // 首先在单例集合中取,大多数情况下,交给IOC管理的Bean都是单例的 // 而且也只有单例模式会存在循环依赖的问题 Object sharedInstance = getSingleton(beanName); // 如果指定了参数的 if (sharedInstance != null && args == null) { // 这里有个小技巧,先判断能否输出日志,再进行组装字符串,避免费劲组装了一大堆字符串却又不需要输出的情况,在工作中可以借鉴 if (logger.isDebugEnabled()) { 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,返回它自己或工厂Bean创建的实例 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { if (isPrototypeCurrentlyInCreation(beanName)) {//如果正在被创建,就抛出异常 throw new BeanCurrentlyInCreationException(beanName); } BeanFactory parentBeanFactory = getParentBeanFactory();//取本容器的父容器 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {//若存在父容器,且本容器不存在对应的Bean定义 String nameToLookup = originalBeanName(name);//取原始的Bean名 if (args != null) {//若参数列表存在 // 那么用父容器根据原始Bean名和参数列表返回 return (T) parentBeanFactory.getBean(nameToLookup, args); } else { // 参数列表不要求,那就直接根据原始名称和要求的类型返回 return parentBeanFactory.getBean(nameToLookup, requiredType); } } //如果不需要类型检查,标记其已经被创建 if (!typeCheckOnly) { markBeanAsCreated(beanName); } //根据beanName取其根Bean定义 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); String[] dependsOn = mbd.getDependsOn();//得到这个根定义的所有依赖 if (dependsOn != null) { for (String dependsOnBean : dependsOn) { getBean(dependsOnBean);//注册这个Bean //注册一个Bean和依赖于它的Bean(后参数依赖前参数) registerDependentBean(dependsOnBean, beanName); } } // 如果Bean定义是单例,就在返回单例 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); //根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } //如果是原型 else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName);//原型创建前,与当前线程绑定 prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName);//原型创建后,与当前线程解除绑定 } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else {//既不是单例又不是原型的情况 String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName);//得到范围 if (scope == null) { throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'"); } try {//根据范围创建实例 Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args);//原型创建前,与当前线程绑定 } finally { ////原型创建后,与当前线程解除绑定 afterPrototypeCreation(beanName); } } }); //根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; " + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } }
相关文章推荐
- Spring源码解析:简单容器中Bean的加载过程初探
- spring容器初始化,bean加载生成过程,源码解析学习
- Spring Bean加载源码解析
- Spring源码解析-bean的加载
- 分析spring源码第五(三)篇:Spring中Bean的解析、加载、创建 过程总结
- Spring源码解析笔记4——bean的加载
- spring源码初步学习-bean的加载
- Spring源码学习IOC(4):IoC容器解析Bean定义资源并注册解析后的Bean
- 看看Spring的源码(一)——Bean加载过程
- 【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
- Spring3.2 中 Bean 定义之基于 XML 配置方式的源码解析
- Spring源码分析-BeanDefinition加载、解析和注册
- Spring3.2 中 Bean 定义之基于 XML 配置方式的源码解析
- spring 源码研究---bean包-- xml解析成bean对象
- 【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
- Spring源码阅读之Bean加载(xml)1
- XmlWebApplicationContext加载bean XML源码解析
- SSH 之 Spring的源码(一)——Bean加载过程
- spring 加载bean过程源码简易解剖(转载)
- Spring源码阅读之Bean加载(annotation )2