`
michael.softtech
  • 浏览: 208429 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

spring代码分析

阅读更多

最近用spring的时候感觉不怎么了解内部原理,用起来有些不习惯,于是找空看了一下spring的源码,看了一下bean加载的流程以及调用流程,现总结如下:

 


加载

 

 contextLoaderListener->ContextLoader.initWebApplicationContext,调用本对象的createWebApplicationContext->ConfigurableWebApplicationContext.refresh()->AbstractApplicationContext.refresh();

在上面的refresh里面有

 

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

   追踪这段代码,发现调用了:AbstractRefreshableApplicationContext的以下方法:

 

 protected final void refreshBeanFactory()
        throws BeansException
    {
        if(hasBeanFactory())
        {
            destroyBeans();
            closeBeanFactory();
        }
        try
        {
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            loadBeanDefinitions(beanFactory);
            synchronized(beanFactoryMonitor)
            {
                this.beanFactory = beanFactory;
            }
        }
        catch(IOException ex)
        {
            throw new ApplicationContextException((new StringBuilder("I/O error parsing bean definition source for ")).append(getDisplayName()).toString(), ex);
        }
    }

    这个方法里面有一句很重要: loadBeanDefinitions(beanFactory);

    这一句的作用是从配置文件加载所有的BeanDefinition.

 

   项目中用到的是基于xml的spring配置方式,所以最终的工厂类是:XmlWebApplicationContext。

   加载beandefinition时,把逐个文件用XmlBeanDefinitionReader进行解析并加载bean。

 

  XmlBeanDefinitionReader首先把每个配置文件载入成一个w3c的Document对象,然后 用 BeanDefinitionDocumentReader解析Document.

 

 BeanDefinitionDocumentReader的实现类是DefaultBeanDefinitionDocumentReader。

 实现类加载bean的方法如下:

 

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
    {
        if(delegate.isDefaultNamespace(delegate.getNamespaceURI(root)))
        {
            NodeList nl = root.getChildNodes();
            for(int i = 0; i < nl.getLength(); i++)
            {
                org.w3c.dom.Node node = nl.item(i);
                if(node instanceof Element)
                {
                    Element ele = (Element)node;
                    String namespaceUri = delegate.getNamespaceURI(ele);
                    if(delegate.isDefaultNamespace(namespaceUri))
                        parseDefaultElement(ele, delegate);
                    else
                        delegate.parseCustomElement(ele);
                }
            }

        } else
        {
            delegate.parseCustomElement(root);
        }
    }

 

   方法中的Element对象root其实就是之前的Document,是一个顶级的Element。

   然后再通过BeanDefinitionParserDelegate解析这个root下面的每个Element,看看是不是下级Element,如果是,

   判断Element是不是默认namespace(比如:beans-这个是默认,security,aop等),如果是:

   调用parseDefaultElement(ele, delegate);否则调用delegate.parseCustomElement(ele)。

   BeanDefinitionParserDelegate是一个很核心的类,这个类完成对bean对应的element的构造函数,bean参数,

   bean的fields的解析并且分别进行保存,之后生成bean的实例的时候需要从中取出这些信息来生成bean实例。

   parseCustomElemen方法的主要作用就是根据namespace调用对用的Namespacehandler解析element并且做   相应的操作(比如:securitynamespacehandler的作用是为应用根据security配置文件添加相应的filter).现在主要集中 在parseDefaultElement 方法上面,这个方法是提取bean的关键方法。

 

   

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
    {
        if(delegate.nodeNameEquals(ele, "import"))
            importBeanDefinitionResource(ele);
        else
        if(delegate.nodeNameEquals(ele, "alias"))
            processAliasRegistration(ele);
        else
        if(delegate.nodeNameEquals(ele, "bean"))
            processBeanDefinition(ele, delegate);
    }

  

  对于在默认namespace下面的常用标签:import,alias,bean,上面的方法都做了处理。下面主要跟踪一下常用的bean的解析: processBeanDefinition。

   

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)
    {
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if(bdHolder != null)
        {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try
            {
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch(BeanDefinitionStoreException ex)
            {
                getReaderContext().error((new StringBuilder("Failed to register bean definition with name '")).append(bdHolder.getBeanName()).append("'").toString(), ele, ex);
            }
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }

 

    至此,真正执行bean解析工作的类出来了:BeanDefinitionParserDelegate 。此类解析Element并且返回一个

    BeanDefinitionHolder 对象。然后通过 

   

 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

 

    支持,把BeanDefinition注册到了beanfactory里面。下面的工作就是取出bean了。

 

 

bean的获取

 

    一个常用的方式是通过ApplicationContext接口来获取bean。getBean(String name)的实现类是AbstractApplicationContext。追踪代码,最终发现bean的获取着落在AbstractBeanFactory的doGetBean方法上。继续跟踪,可以跟踪到:AbstractAutowireCapableBeanFactory的doCreateBean方法(对于Prototype的bean),此方法的作用是创建bean的实例。跟踪以上方法,发现是依靠InstantiationStrategy来实例化bean。

有两张策略来实例化bean: SimpleInstantiationStrategy,CglibSubclassingInstantiationStrategy。从名字上很容易看出,前者是不用代理的实例化,后者是通过cglib生成代理类对象的实例化。

 

至此,bean的取出过程也大概清楚了。因为时间仓促,很多细节来不及描述,等有空了补全这篇文章。

   

   

 

 

 
   

0
0
分享到:
评论

相关推荐

    Spring源码分析.pdf

    Spring 源码分析 Spring 框架是 Java 语言中最流行的开源框架之一,它提供了一个强大且灵活的基础设施来构建企业级应用程序。在 Spring 框架中,IOC 容器扮演着核心角色,本文将深入分析 Spring 源码,了解 IOC ...

    Spring源码解析.zip

    本压缩包“Spring源码解析”提供了对Spring框架核心组件——IOC(Inversion of Control,控制反转)、AOP(Aspect Oriented Programming,面向切面编程)以及Transaction(事务管理)的源码分析,帮助开发者更全面地...

    Spring源码解析.pdf

    ### Spring源码解析知识点 #### 一、Spring IoC 容器详解 ##### 1. BeanFactory —— 最基础的IoC容器 - **概念**:`BeanFactory` 是Spring框架中最基本的IoC容器,它负责管理Bean的生命周期,包括创建、配置和...

    spring源码分析(1-10)

    Spring 源代码分析系列涵盖了多个关键模块,包括事务处理、IoC容器、JDBC、MVC、AOP以及与Hibernate和Acegi安全框架的集成。以下是对这些知识点的详细阐述: 1. **Spring 事务处理**:Spring 提供了声明式事务管理...

    spring源码分析

    《Spring源码分析》 Spring框架作为Java领域中不可或缺的一部分,其强大之处在于它提供了丰富的功能,包括依赖注入(Dependency Injection,简称DI)、面向切面编程(Aspect-Oriented Programming,简称AOP)、事务...

    spring源码分析专题学习资源

    spring源码分析专题,源码分析视频,对spring的源码进行分析

    spring源码解析

    10. **源码分析**:深入阅读Spring的源码可以帮助理解其设计思想和实现机制,比如Bean的生命周期、AOP的代理过程、事件驱动模型等。 通过"spring源码解析"的学习,开发者可以更好地理解和利用Spring框架,提升开发...

    Spring源码深度解析第二版

    Spring源码深度解析第二版 Spring是一款广泛应用于Java企业级应用程序的开源框架,旨在简化Java应用程序的开发和部署。Spring框架的核心主要包括了IoC容器、AOP、MVC框架等模块。 第1章 Spring整体架构和环境搭建 ...

    spring源码解析和mybatis学习

    6. **Spring源码分析**:通过阅读源码,理解Spring框架的工作原理,增强对框架的深入理解。 接下来,我们转向MyBatis,这是一个轻量级的持久层框架,它提供了灵活的SQL映射机制,使得数据库操作变得简单。"MyBatis3...

    Spring源码分析

    以上只是Spring源码分析的部分内容,实际源码中还包括Spring的其他模块,如Spring Batch(批处理)、Spring Security(安全)、Spring Integration(集成)等。理解并掌握Spring源码,有助于我们更好地利用Spring...

    Spring5 源码分析(第 2 版)-某Tom老师

    《Spring5 源码分析(第 2 版)》是某Tom老师精心编写的深度解析文档,旨在帮助读者全面理解Spring5的核心机制和设计理念。Spring作为Java领域最为广泛应用的框架之一,其源码的深入理解对于开发者来说至关重要。这篇...

    Spring源码解析

    本文将围绕Spring的核心概念和关键组件,通过源码分析,帮助你深入理解Spring的工作原理。 首先,Spring的核心是依赖注入(Dependency Injection,DI),它是控制反转(Inversion of Control,IoC)的一种实现方式...

    spring源码分析流程全面解析

    总之,Spring源码分析是提升Java开发者技术水平的重要途径,它能够帮助我们更有效地利用Spring框架,优化代码,解决复杂问题,同时也能为面试做好充分准备。通过深入学习Spring的各个组成部分,我们可以成为更优秀的...

    Spring5 源码分析(第 2 版) .zip

    《Spring5 源码分析(第 2 版)》是针对Spring框架第五个主要版本的深度解析著作,由知名讲师倾心打造,旨在帮助读者深入理解Spring框架的内部工作机制,提升对Java企业级应用开发的专业技能。本书涵盖了Spring框架的...

    Spring源码分析.txt

    spring源码分析,百度云视频。链接如果失效了,请私聊我。

    spring 源码中文注释

    在源码分析的过程中,读者会深入理解Spring的内部工作机制,例如如何解析配置、如何创建bean实例、如何实现AOP代理等。这将有助于开发者编写更高效、更健壮的代码,也能为参与Spring的扩展或定制打下坚实基础。 总...

    Spring核心源码解析.pdf

    本篇文档将对Spring框架的核心源码进行解析,以帮助开发者更深入地理解Spring的工作原理和核心概念。 首先,Spring框架通过使用IoC容器来管理应用对象的创建和依赖关系。这种做法可以让程序员从创建对象的复杂性中...

    Spring源码分析_Spring_IOC

    ### Spring源码分析_Spring_IOC:深入理解Spring的IOC容器机制 #### 基本概念与核心作用 在探讨Spring框架的核心组件之一——IOC(Inversion of Control,控制反转)容器之前,首先需要理解它在Spring框架中的角色...

Global site tag (gtag.js) - Google Analytics