• 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中static的特点
  • 2017-05-28JAVA线程sleep()和wait()详解及实例
  • 2017-05-28Hibernate对数据库删除、查找、更新操作实例代码
  • 2017-05-28Spring Boot集成Redis实现缓存机制(从零开始学Spring Boot)
  • 2017-05-28java 中动态代理(JDK,cglib)实例代码
  • 2017-05-28详解使用Spring3 实现用户登录以及权限认证
  • 2017-05-28Spring Boot集成MyBatis访问数据库的方法
  • 2017-05-28Java 读取外部资源的方法详解及实例代码
  • 2017-05-28Spring Hibernate实现分页功能
  • 2017-05-28浅谈JavaWeb中的web.xml配置部署描述符文件

文章分类

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

最近更新的内容

    • 详解SpringBoot AOP 拦截器(Aspect注解方式)
    • 浅析Java中clone()方法浅克隆与深度克隆
    • 学习Spring-Session+Redis实现session共享的方法
    • 命令提示符编译java的方法(必看篇)
    • 浅谈java中为什么实体类需要实现序列化
    • 详解Spring Aop实例之xml配置
    • 详解Spring中Bean的生命周期和作用域及实现方式
    • [译]深入字节码操作:使用ASM和Javassist创建审核日志
    • Mybaits配置文件之动态SQL配置备忘录
    • 利用Spring boot如何创建简单的web交互应用

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

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