Spring源码解析之Bean的加载
来源:互联网 发布:nginx反向代理配置文件 编辑:程序博客网 时间:2024/04/29 05:24
本文基于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); } } }
0 0
- Spring源码解析之Bean的加载
- Spring源码解析-bean的加载
- Spring Bean加载源码解析
- Spring源码之bean的加载(一)
- Spring源码之bean的加载(五)准备创建bean
- spring源码深度解析(笔记四)--bean的加载
- Spring源码之bean的加载(四)获取单例
- spring源码阅读之Bean的加载(一)
- spring源码阅读之Bean的加载(二)
- Spring源码分析之Bean的加载流程
- Spring源码阅读之-bean的解析与注册
- spring源码解析之bean的子元素
- Spring源码解析之bean的创建和销毁
- spring源码初步学习-bean的加载
- Spring源码(四)-bean的加载(上)
- Spring源码(五)-bean的加载(下)
- Spring源码之bean的加载(二)获取单例bean
- Spring源码之bean的加载(三)从bean中获取对象
- 【VC编程】笔记1--创建一个Win32的应用程序,并显示创建的窗口和菜单
- 作业2
- 自定义InputFormat
- 计算机大牛网站
- 再谈事件封装性
- Spring源码解析之Bean的加载
- 关键字const的作用
- springDao-配置数据源
- Java transient关键字使用小记
- RESTful
- 谈谈图像的Style Transfer(一)
- poj 1654 Area (叉积求面积)
- python创建型设计模式——建造者模式
- 51nod 1095 Anigram单词