• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Java > 详解Spring中Bean的加载的方法

详解Spring中Bean的加载的方法

作者:weknow 字体:[增加 减小] 来源:互联网 时间:2017-05-28

weknow 通过本文主要向大家介绍了spring中bean的作用域,spring 获取bean,spring中bean是什么,spring boot bean,spring bean等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

之前写过bean的解析,这篇来讲讲bean的加载,加载要比bean的解析复杂些,从之前的例子开始.

Spring中加载一个bean的方式:

TestBean bean = factory.getBean("testBean");
</div>

来看看getBean(String name)方法源码,

@Override
public Object getBean(String name) throws BeansException {
  return doGetBean(name, null, null, false);
}
</div>

该getBean(String name)方法位于AbstractBeanFactory抽象类中,AbstractBeanFactory与XmlBeanFactory类关系可以看下图:

接下去跟进doGetBean()方法源码:

protected <T> T doGetBean(
    final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
    throws BeansException {
  // 提取beanName
  final String beanName = transformedBeanName(name);
  Object 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 + "'");
      }
    }
    // 返回实例,有时存在如BeanFactory这样情况时并不是直接返回实例本身而是返回指定方法返回的实例
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  }

  else {
    // Fail if we're already creating this bean instance:
    // We're assumably within a circular reference.
    if (isPrototypeCurrentlyInCreation(beanName)) {
      throw new BeanCurrentlyInCreationException(beanName);
    }

    // Check if bean definition exists in this factory.
    BeanFactory parentBeanFactory = getParentBeanFactory();
    // 如果在所有已经加载的类中没有beanName则会尝试从parentBeanFactory中检测
    if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
      // Not found -> check parent.
      String nameToLookup = originalBeanName(name);
      // 到BeanFactory查找
      if (args != null) {
        // Delegation to parent with explicit args.
        return (T) parentBeanFactory.getBean(nameToLookup, args);
      }
      else {
        // No args -> delegate to standard getBean method.
        return parentBeanFactory.getBean(nameToLookup, requiredType);
      }
    }
    // 如果不是只做类型检查则是创建bean
    if (!typeCheckOnly) {
      markBeanAsCreated(beanName);
    }

    try {
      // 将存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,如果BeanName是子Bean的话会合并父类的相关属性
      final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
      checkMergedBeanDefinition(mbd, beanName, args);

      // Guarantee initialization of beans that the current bean depends on.
      String[] dependsOn = mbd.getDependsOn();
      // 如果存在依赖的话要递归实例化依赖的bean
      if (dependsOn != null) {
        for (String dependsOnBean : dependsOn) {
          if (isDependent(beanName, dependsOnBean)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
          }
          registerDependentBean(dependsOnBean, beanName);
          getBean(dependsOnBean);
        }
      }

      // Create bean instance.
      // 依赖的bean实例化完后就可以实例化mbd了
      if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
          @Override
          public Object getObject() throws BeansException {
            try {
              return createBean(beanName, mbd, args);
            }
            catch (BeansException ex) {
              // Explicitly remove instance from singleton cache: It might have been put there
              // eagerly by the creation process, to allow for circular reference resolution.
              // Also remove any beans that received a temporary reference to the bean.
              destroySingleton(beanName);
              throw ex;
            }
          }
        });
        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 {
        // 在对应的scope上实例化bean
        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>() {
            @Override
            public Object getObject() throws BeansException {
              beforePrototypeCreation(beanName);
              try {
                return createBean(beanName, mbd, args);
              }
              finally {
                afterPrototypeCreation(beanName);
              }
            }
          });
          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);
        }
      }
    }
    catch (BeansException ex) {
      cleanupAfterBeanCreationFailure(beanName);
      throw ex;
    }
  }

  // 检查需要的类型是否符合实例bean的实际类型
  if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
    try {
      return getTypeConverter().convertIfNecessary(bean, requiredType);
    }
    catch (TypeMismatchException ex) {
      if (logger.isDebugEnabled()) {
        logger.debug("Failed to convert bean '" + name + "' to required type [" +
            ClassUtils.getQualifiedName(requiredType) + "]", ex);
      }
      throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    }
  }
  return (T) bean;
}
</div>

整个bean加载的过程步骤相对繁琐,主要步骤有以下几点:

1、转换beanName

要知道平时开发中传入的参数name可能只是别名,也可能是FactoryBean,所以需要进行解析转换,一般会进行以下解析:

(1)消除修饰符,比如name="&test",会去除&使name="test";

(2)取alias表示的最后的beanName,比如别名test01指向名称为test02的bean则返回test02。

2、从缓存中加载实例

实例在Spring的同一个容器中只会被创建一次,后面再想获取该bean时,就会尝试从缓存中获取;如果获取不到的话再从singletonFactories中加载。

3、实例化bean

缓存中记录的bean一般只是最原始的bean状态,这时就需要对bean进行实例化。如果得到的是bean的原始状态,但又要对bean进行处理,这时真正需要的是工厂bean中定义的factory-method方法中返回的bean,上面源码中的getObjectForBeanInstance就是来完成这个工作的。

4、检测parentBeanFacotory

从源码可以看出如果缓存中没有数据会转到父类工厂去加载,源码中的!containsBeanDefinition(beanName)就是检测如果当

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • spring之Bean的生命周期详解
  • 详解Spring中bean实例化的三种方式
  • 详解Spring中Bean的加载的方法
  • 深入理解Spring中bean的生命周期介绍
  • 详解Spring中Bean的生命周期和作用域及实现方式
  • spring之Bean的生命周期详解
  • 详解Spring中bean实例化的三种方式
  • 详解Spring中Bean的加载的方法

相关文章

  • 2017-05-28Java Date类常用示例_动力节点Java学院整理
  • 2017-05-28java IO 文件操作方法总结
  • 2017-05-28java读取txt文件代码片段
  • 2017-05-28Java中抽象类和接口的区别_动力节点Java学院整理
  • 2017-05-28java实现将汉语转换为拼音功能
  • 2017-05-28ByteArrayOutputStream简介和使用_动力节点Java学院整理
  • 2017-05-28在mybatis执行SQL语句之前进行拦击处理实例
  • 2017-05-28浅谈java中类名.class, class.forName(), getClass()的区别
  • 2017-05-28Java微信公众平台开发(15) 微信JSSDK的使用
  • 2017-05-28java实现ftp文件上传下载功能

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 如何把spring boot项目部署到tomcat容器中
    • Java中自定义异常详解及实例代码
    • Spring Boot(五)之跨域、自定义查询及分页
    • Java Scaner类详解_动力节点Java学院整理
    • java实现短信通信的完整教程
    • Spring boot 整合CXF开发web service示例
    • Java中final,finally,finalize三个关键字的区别_动力节点Java学院整理
    • Spring+SpringMVC+MyBatis深入学习及搭建(三)之MyBatis全局配置文件解析
    • HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别
    • Java通过正则表达式获取字符串中数字的方法示例

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有