知识大全 spring代码分析

Posted

篇首语:男儿欲遂平生志,五经勤向窗前读。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 spring代码分析相关的知识,希望对你有一定的参考价值。

  在Spring中 IOC容器的重要地位我们就不多说了 对于Spring的使用者而言 IOC容器实际上是什么呢?我们可以说BeanFactory就是我们看到的IoC容器 当然了Spring为我们准备了许多种IoC容器来使用 这样可以方便我们从不同的层面 不同的资源位置 不同的形式的定义信息来建立我们需要的IoC容器

  在Spring中 最基本的IOC容器接口是BeanFactory 这个接口为具体的IOC容器的实现作了最基本的功能规定 不管怎么著 作为IOC容器 这些接口你必须要满足应用程序的最基本要求

  public interface BeanFactory

  //这里是对FactoryBean的转义定义 因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象

  //如果需要得到工厂本身 需要转义

  String FACTORY_BEAN_PREFIX = & ;

  //这里根据bean的名字 在IOC容器中得到bean实例 这个IOC容器就是一个大的抽象工厂

  Object getBean(String name) throws BeansException;

  //这里根据bean的名字和Class类型来得到bean实例 和上面的方法不同在于它会抛出异常 如果根据名字取得的bean实例的Class类型和需要的不同的话

  Object getBean(String name Class requiredType) throws BeansException;

  //这里提供对bean的检索 看看是否在IOC容器有这个名字的bean

  boolean containsBean(String name);

  //这里根据bean名字得到bean实例 并同时判断这个bean是不是单件

  boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

  //这里对得到bean实例的Class类型

  Class getType(String name) throws NoSuchBeanDefinitionException;

  //这里得到bean的别名 如果根据别名检索 那么其原名也会被检索出来

  String[] getAliases(String name);

  

  在BeanFactory里只对IOC容器的基本行为作了定义 根本不关心你的bean是怎样定义怎样加载的 就像我们只关心从这个工厂里我们得到到什么产品对象 至于工厂是怎么生产这些对象的 这个基本的接口不关心这些 如果要关心工厂是怎样产生对象的 应用程序需要使用具体的IOC容器实现 当然你可以自己根据这个BeanFactory来实现自己的IOC容器 但这个没有必要 因为Spring已经为我们准备好了一系列工厂来让我们使用 比如XmlBeanFactory就是针对最基础的BeanFactory的IOC容器的实现 这个实现使用xml来定义IOC容器中的bean

  

  文以spring框架的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);

  

  

  这个类的代码很简单 一个成员对象加两个构造函数 从这里我们可以看出 最重要的地方在于最后一个构造函数

  第一句就是将父亲工厂交给父类的构造函数 实际上最后也就是把父工厂保存到类的parentBeanFactory成员对象中 这个对象是在AbstractBeanFactory抽象类中定义的 而这个父工厂也会一直传递到该抽象类进行保存 第二句就是整个类中最重要的地方了 顾名思义 它的目的是通过XmlBeanDefinitionReader这个XML的Reader从资源resource中(也就是你的配置文件)读取bean的定义 接下来我们打开XmlBeanDefinitionReader的loadBeanDefinitions方法 我们可看到在这个方法里代码就一行 调用了一个同名不同参的方法 而参数是EncodedResource的一个实例 这个类实际上是Resource的一个包装类 用来保存资源的Encode的 那接下来我们再看被调用的loadBeanDefinitions方法 这个方法里最主要的部分就是

  InputSource inputSource = new InputSource(inputStream);

  if (encodedResource getEncoding() != null)

  inputSource setEncoding(encodedResource getEncoding());

  

  return doLoadBeanDefinitions(inputSource encodedResource getResource());

  这里的目的是将资源包装成一个InputSource 连同Resource作为参数传递到doLoadBeanDefinitions方法

  DocumentBuilderFactory factory = createDocumentBuilderFactory();

  if (logger isDebugEnabled())

  logger debug( Using JAXP implementation [ + factory + ] );

  

  DocumentBuilder builder = createDocumentBuilder(factory);

  Document doc = builder parse(inputSource);

  return registerBeanDefinitions(doc resource);

  这个方法的目的一目了然 就是为了将资源解释成为Document对象 然后调用registerBeanDefinitions方法 这里不做详细解释 不了解的话请去看看关于JAXP的介绍 接下来我们打开registerBeanDefinitions方法

  public int registerBeanDefinitions(Document doc Resource resource) throws BeansException

  XmlBeanDefinitionParser parser =

  (XmlBeanDefinitionParser) BeanUtils instantiateClass(this parserClass);

  return parser registerBeanDefinitions(this doc resource);

  

  这里创建了一个XmlBeanDefinitionParser接口的实现 这个接口的具体类是DefaultXmlBeanDefinitionParser 这个接口很简单 只有registerBeanDefinitions一个方法 这个方法的作用也很明了 就是用来注册Bean的定义的 所以说类和方法的名字一定要起得有意义 这样可以让人一看就大概了解其作用 减少了很多阅读代码的痛苦 废话不多说 我们打开DefaultXmlBeanDefinitionParser的registerBeanDefinitions方法 这个类就是解释XML配置文件的核心类了 打开registerBeanDefinitions方法后我们看到如下代码

  public int registerBeanDefinitions(BeanDefinitionReader reader Document doc Resource resource)

  throws BeanDefinitionStoreException

  this beanDefinitionReader = reader;

  this resource = resource;

  logger debug( Loading bean definitions );

  Element root = doc getDocumentElement();

  //初始化根元素

  initDefaults(root);

  if (logger isDebugEnabled())

  logger debug( Default lazy init + getDefaultLazyInit() + );

  logger debug( Default autowire + getDefaultAutowire() + );

  logger debug( Default dependency check + getDefaultDependencyCheck() + );

  

  preProcessXml(root);//一个空方法用于扩展

  int beanDefinitionCount = parseBeanDefinitions(root);//解释配置的主要方法

  if (logger isDebugEnabled())

  logger debug( Found + beanDefinitionCount + <bean> elements in + resource);

  

  postProcessXml(root); //一个空方法用于扩展

  return beanDefinitionCount;

  

  在这个方法当中 主要用于解释定义的有两个方法 一个是initDefaults 一个是parseBeanDefinitions 第一个方法是用来解释根元素的属性的 例如lazy init autowire等 而parseBeanDefinitions就是用来解释具体的bean定义了 方法代码如下

  protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException

  NodeList nl = root getChildNodes();

  int beanDefinitionCount = ;

  for (int i = ; i < nl getLength(); i++)

  Node node = em(i);

  if (node instanceof Element)

  Element ele = (Element) node;

  if (IMPORT_ELEMENT equals(node getNodeName()))

  importBeanDefinitionResource(ele);

  

  else if (ALIAS_ELEMENT equals(node getNodeName()))

  String name = ele getAttribute(NAME_ATTRIBUTE);

  String alias = ele getAttribute(ALIAS_ATTRIBUTE);

  this beanDefinitionReader getBeanFactory() registerAlias(name alias);

  

  else if (BEAN_ELEMENT equals(node getNodeName()))

  beanDefinitionCount++;

  BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele false);

  BeanDefinitionReaderUtils registerBeanDefinition(bdHolder this beanDefinitionReader getBeanFactory());

  

  

  

  return beanDefinitionCount;

  

  其他标签具体如何被解释这里就不多说 相信大家也能看得懂 这里主要讲一下解释bean的的处理 我们注意以下代码

  else if (BEAN_ELEMENT equals(node getNodeName()))

  beanDefinitionCount++;

  BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele false);

  BeanDefinitionReaderUtils registerBeanDefinition(bdHolder this beanDefinitionReader getBeanFactory());

  

  这里是当碰到一个bean标签的时候所进行的处理 也既是对bean的定义进行解释 可以看到parseBeanDefinitionElement方法的第一个参数就是bean则个元素 第二个参数表示该bean是否为内置的bean 从这里进行解释的bean都不可能是内置的 所以这里直接以false为参数 打开parseBeanDefinitionElement方法 就可以看到这个方法里就是对bean的内部的解释 也很简单 也不多讲了 呵呵(下班时间已经到了 所以就写这么多了 基本的流程也就这样 没什么特别难的地方 ) 对了 最后还有一点就是解释完后 bean的定义将会被保存到beanFactory中 这个beanFactory的实现就是XmlBeanFactory了 该beanFactory是在new的时候被传递到reader中的 就是该类中以下这行代码

cha138/Article/program/Java/ky/201311/28593

相关参考

知识大全 spring技术手册上的一个java动态代理例子

  Java代码  publicinterfaceIHello  publicvoidhello(Stringname);    Java代码  publicclassHelloImplimpleme

知识大全 开源技术分析:AOP和Spring事务处理

开源技术分析:AOP和Spring事务处理  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  一为什

知识大全 对Spring中接口注入的理解实例分析

对Spring中接口注入的理解实例分析  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Type接

知识大全 Spring框架的设计理念与设计模式分析

Spring框架的设计理念与设计模式分析  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Spri

知识大全 Spring MVC framework深入总体分析

SpringMVCframework深入总体分析  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 用spring简单实现发送邮件

  刚做完一个电影网站网站新注册用户时需要发送email进行确认但是这个功能不是由我来负责的在下对此功能颇有好奇之心于是自己就搭建了一个小的spring项目来进行实践  声明代码里有些内容并非是我一个

知识大全 Spring中事件处理的小技巧[4]

Spring中事件处理的小技巧[4]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  java代码

知识大全 Spring中事件处理的小技巧[3]

Spring中事件处理的小技巧[3]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  java代码

知识大全 Spring中事件处理的小技巧[2]

Spring中事件处理的小技巧[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  java代码

知识大全 在spring中有几种事务管理,分别是什么?

代码管理的事务处理TransactonTemplate的execute方法中的内部类TransactionCallback中的doInTransaction方法中使用publicvoidmake()?