• 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中BeanFactory解析bean详解

Spring中BeanFactory解析bean详解

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

weknow619 通过本文主要向大家介绍了spring beanfactory,beanfactory,beanfactoryaware,beanfactory.getbean,java beanfactory等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

在该文中来讲讲Spring框架中BeanFactory解析bean的过程,该文之前在小编原文中有发表过,先来看一个在Spring中一个基本的bean定义与使用。

package bean;
public class TestBean {
  private String beanName = "beanName";
  public String getBeanName() {
    return beanName;
  }
  public void setBeanName(String beanName) {
    this.beanName = beanName;
  }
}
</div>

Spring配置文件root.xml定义如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

  <bean id="testBean" class="bean.TestBean">
</beans>
</div>

下面使用XmlBeanFactory来获取该bean:

public class BeanTest {

  private static final java.util.logging.Logger logger = LoggerFactory.getLogger(BeanTest.class);

  @Test
  public void getBeanTest() {
    BeanFactory factory = new XmlBeanFactory(new ClassPathResource("root.xml"));
    TestBean bean = factory.getBean("testBean");
    logger.info(bean.getBeanName);
  }
}
</div>

这个单元测试运行结果就是输出beanName,上面就是Spring最基本的bean的获取操作,这里我用BeanFactory作为容器来获取bean的操作并不多见,在企业开发中一般是使用功能更完善的ApplicationContext,这里先不讨论这个,下面重点讲解使用BeanFactory获取bean的过程。

现在就来分析下上面的测试代码,看看Spring到底为我们做了什么工作,上面代码完成功能的流程不外乎如此:

1. 读取Spring配置文件root.xml;

2. 根据root.xml中的bean配置找到对应的类的配置,并实例化;

3. 调用实例化后的对象输出结果。

先来看看XmlBeanFactory源码:

public class XmlBeanFactory extends DefaultListableBeanFactory {

  private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

  public XmlBeanFactory(Resource resource) throws BeansException {
    this(resource, null);
  }

  public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
    super(parentBeanFactory);
    this.reader.loadBeanDefinitions(resource);
  }
}
</div>

从上面可以看出XmlBeanFactory继承了DefaultListableBeanFactory,DefaultListableBeanFactory是Spring注册加载bean的默认实现,它是整个bean加载的核心部分,XmlBeanFactory与它的不同点就是XmlBeanFactory使用了自定义的XML读取器XmlBeanDefinitionReader,实现了自己的BeanDefinitionReader读取。

XmlBeanFactory加载bean的关键就在于XmlBeanDefinitionReader,下面看看XmlBeanDefinitionReader的源码(只列出部分):

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {

  private Class<?> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;

  private ProblemReporter problemReporter = new FailFastProblemReporter();

  private ReaderEventListener eventListener = new EmptyReaderEventListener();

  private SourceExtractor sourceExtractor = new NullSourceExtractor();

  private NamespaceHandlerResolver namespaceHandlerResolver;

  private DocumentLoader documentLoader = new DefaultDocumentLoader();

  private EntityResolver entityResolver;

  private ErrorHandler errorHandler = new SimpleSaxErrorHandler(logger);
}
</div>

XmlBeanDefinitionReader继承自AbstractBeanDefinitionReader,下面是AbstractBeanDefinitionReader的源码(只列出部分):

public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable, BeanDefinitionReader {

  protected final Log logger = LogFactory.getLog(getClass());

  private final BeanDefinitionRegistry registry;

  private ResourceLoader resourceLoader;

  private ClassLoader beanClassLoader;

  private Environment environment;

  private BeanNameGenerator beanNameGenerator = new DefaultBeanNameGenerator();
}
</div>

XmlBeanDefinitionReader主要通过以下三步来加载Spring配置文件中的bean:

1. 通过继承自AbstractBeanDefinitionReader中的方法,使用ResourLoader将资源文件(root.xml)路径转换为对应的Resource文件;

2. 通过DocumentLoader对Resource文件进行转换,将Resource文件转换为Ducument文件;

3. 通过DefaultBeanDefinitionDocumentReader类对Document进行解析,最后再对解析后的Element进行解析。

了解以上基础后,接下来详细分析下一开始例子中的代码:

BeanFactory factory = new XmlBeanFactory(new ClassPathResource("root.xml"));
</div>

先看看下面XmlBeanFactory初始化的时序图来进一步了解这段代码的执行,

在这里可以看出BeanTest测试类通过向ClassPathResource的构造方法传入spring的配置文件构造一个Resource资源文件的实例对象,再通过这个Resource资源文件来构造我们想要的XmlBeanFactory实例。在前面XmlBeanFactory源码中的构造方法可以看出,

public XmlBeanFactory(Resource resource) throws BeansException {
   this(resource, null);
}

public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
   super(parentBeanFactory);
   this.reader.loadBeanDefinitions(resource);
}
</div>

this.reader.loadBeanDefinition(resource)就是资源加载真正的实现,时序图中XmlBeanDefinitionReader加载数据就是在这里完成的。

接下来跟进this.reader.loadBeanDefinition(resource)方法里面,

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {

  @Override
  public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(new EncodedResource(resource));
  }
}
</div>

在loadBeanDefinition(resource)方法里对资源文件resource使用EncodedResource进行编码处理后继续传入loadBeanDefinitions方法,继续跟进loadBeanDefinitions(new EncodedResource(resource))方法源码:

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
  Assert.notNull(encodedResource, "EncodedResource must not be null");
  if (logger.isInfoEnabled()) {
    logger.info("Loading XML bean definitions from " + encodedResource.getResource());
  }

  // 通过属性记录已加载的资源
  Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
  if (currentResources == null) {
    currentResources = new HashSet<EncodedResource>(4);
    this.resourcesCurrentlyBeingLoaded.set(currentResources);
  }
  if (!currentResources.add(encodedResource)) {
    throw new BeanDefinitionStoreException(
        "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
  }
  try {
    // 从resource中获取对应的InputStream,用于下面构造InputSource
    InputStream inputStream = encodedResource.getResource().getInputStream();
    try {
      InputSource inputSource = new InputSource(inputStream);
      if (encodedResource.getEncoding() != null) {
        inputSource.setEncoding(encodedResource.getEncoding());
      }
      // 调用doLoadBeanDefinitions方法
      return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    }
    finally {
      inputStream.close();
    }
  }
  catch (IOException ex) {
    throw new BeanDefinitionStoreException(
        "IOException parsing XML document from " + encodedResource.getResource(), ex);
  }
  finally {
    currentResources.remove(encodedResource);



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

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

  • Spring中BeanFactory解析bean详解

相关文章

  • 2017-05-28详解spring boot中使用JdbcTemplate
  • 2017-05-28Java数据结构与算法之选择排序(动力节点java学院整理)
  • 2017-05-28BufferedInputStream(缓冲输入流)详解_动力节点Java学院整理
  • 2017-05-28Java中LinkedList详解和使用示例_动力节点Java学院整理
  • 2017-05-28Android 应用按返回键退向后台运行实例代码
  • 2017-05-28Java多线程中的单例模式两种实现方式
  • 2017-05-28详解Spring Boot 部署与服务配置
  • 2017-05-28SpringBoot JPA 表关联查询实例
  • 2017-05-28Java项目开发命名规范(动力节点Java学院整理)
  • 2017-05-28Java 中的CharArrayReader 介绍_动力节点Java学院整理

文章分类

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

最近更新的内容

    • Java使用File类遍历目录及文件实例代码
    • java实现微信H5支付方法详解
    • 简单谈谈RxJava和多线程并发
    • Spring Data JPA 简单查询--方法定义规则(详解)
    • springboot中thymeleaf模板使用详解
    • Spring Boot中Redis数据库的使用实例
    • 详解使用zxing库生成QR-Code二维码
    • Java常用数字工具类 数字转汉字(1)
    • JavaEE开发基于Eclipse的环境搭建以及Maven Web App的创建
    • Java面试问题知识点总结

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

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