Spring原理-核心模块

最近想了解一下Spring的原理,看了一些文章和书还有源码,稍微了解了一点,把这些东西总结一下,方便以后回忆。


一,Spring核心模块介绍

在这之前,需要看一下这篇文章(https://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/#icomments),

这篇文章把Spring核心模块的轮廓描述的非常清晰,文章把核心模块分为三个:Beans,Context,Core。实际上,Spring的Jar包也是这样分的,Spring-Beans-X.X.X.jar,Spring-Context-X.X.X.jar,Spring-Core-X.X.X.jar。在这三个模块中,最重要的是Beans模块,这个模块用来生成和管理Spring的Beans,Spring所有的功能都是围绕Bean来进行的。


二,Spring核心模块解析

    如果 你已经看完了上面介绍的文章,那你对Spring的核心有了大概的了解,接下来我们解析一下每个模块大概的功能。

    为了好理解,把上面文章中的图给拿过来参考。

图 4. Bean 工厂的继承关系

Bean模块:

    首先要介绍的是Bean模块,这里介绍一下这个模块比较重要的接口,不介绍接口的实现类。因为这个模块中,可供我们进行配置或定制的地方比较少,用的比较多的还是Context模块中的ApplicationContext接口和它的实现类,所以会在后台多介绍一下ApplicationContext。

    重要的接口如下:

    - BeanFactory

    - HierarchicalBeanFactory

    - ConfigurableBeanFactory

    - ListableBeanFactory

    - ConfigurableListableBeanFactory

    - AutowireCapableBeanFactory


BeanFactory:

BeanFactory是Spring bean容器的根接口。它只提供了一些最基本的接口,查找是否包含Bean,取得Bean,Bean是Singleton还是Prototype的等操作。
每个bean都是通过string类型bean name进行标识.这边提供了设计模式单例,原型的替代实现。它的实现类其实就是利用BeanDefinition来生成Bean,而这些BeanDefinition是用名字来实现唯一性的。

HierarchicalBeanFactory:

继承了BeanFactory,增加了两个方法containsLocalBean(String name),getParentBeanFactory(),增加了取得对父容器对象的操作。至于如何使用,可以参看这个例子:http://www.java3z.com/article/article2/spring4.html。但在我们的实际应用中,应该在什么场景下使用这个Factory,还没有想到。

ConfigurableBeanFactory:

这个接口的前面有Configurable,意思是这个一个可以添加一些自定义配置的BeanFactory。例如增加了addBeanPostProcessor这类方法,可以在Bean初始化后,增加一些用户自定义的操作。继承了很多接口,其中有一个接口就是HierarchicalBeanFactory,在继承这个接口后,增加了一个和这个接口相关的方法:setParentBeanFactory (BeanFactory parentBeanFactory)。有了这个方法后,就可以设置父容器对象了。一般HierarchicalBeanFactory和ConfigurableBeanFactory都是成对继承的,如果只继承HierarchicalBeanFactory,而不继承ConfigurableBeanFactory的话,就无法设置父容器了。


ListableBeanFactory:

BeanFactory只定义了取得单个Bean的方法,并没有定义取得所有Bean,和所有BeanName,以及所有BeanDefinition的方法。ListableBeanFactory就定义了上面说的BeanFactory没有定义的方法,可以把它看作是BeanFactory的增强版。比如增加了对BeanDefinition的找到和取得方法containsBeanDefinition, getBeanDefinitionNames, getBeanDefinitionCount等。和取得所有BeanName的方法:getBeanNamesForAnnotation,getBeanNamesForType,它们的返回类型都是String[]。和取得所有Bean的方法getBeansOfType,getBeansWithAnnotation等。


ConfigurableListableBeanFactory:

看名字就能看出来,它是一个可配置的ListableBeanFactory。这个接口集成了很多接口算是一个大集合。除了实现了ConfigurableBeanFactory的功能,还提供了分析和修改BeanDefinition,预先初始化singleton的功能。


AutowireCapableBeanFactory:

在BeanFactory基础上实现对已存在实例的管理。可以使用这个接口集成其它框架,捆绑并填充并不由Spring管理生命周期并已存在的实例.像集成WebWork的Actions 和Tapestry Page就很实用。一般应用开发者不会使用这个接口,所以像ApplicationContext这样的外观实现类不会实现这个接口,如果真手痒痒可以通过ApplicationContext的getAutowireCapableBeanFactory接口获取。


关于实现类,其中的一个实现类就是DefaultListableBeanFactory,它是一非常重要的IoC实现。这个类实现了XmlBeanFactory就是使用这个类作为基类。ApplicationContext接口的实现类(AbstractRefreshableApplicationContext),也是通过持有DefaultListableBeanFactory的对象,来实现IoC容器的基本功能。

对于XmlBeanFactory这个类,它也是实现类之一,它的实现方式是以编程的方式来使用DefaultListableBeanFactory。从中可以看到IoC容器使用的一些基本过程。尽管我们在应用中使用IoC容器时,很少会使用这种原始的方式,但了解一下这个基本过程,对我们理解IoC容器的工作原理是非常有帮助的。因为这个编程式使用容器的过程,很清楚地揭示了IoC容器实现中的那些关键的类(比如:Resource,DefaultListableBeanFactory和BeanDefinitionReader)之间的关系,例如他们是如何把IoC容器的功能解耦合的,又是如何在一起为IoC容器服务的。

例如:XmlBeanFactory的实现方式就是以下的代码

public class XmlBeanFactory extends DefaultListableBeanFactory {

    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

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

1,private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

声明一个Reader,并把自己(XmlBeanFactory)当做参数传Reader。因为DefaultListableBeanFactory实现了ResourceLoader接口,使用这个功能来读取Resource。

2,this.reader.loadBeanDefinitions(resource);

使用Reader的loadBeanDefinitions方法,来读取Resource中的BeanDefinition,把Bean加载到Factory里(todo:应该是,还没有仔细读源码去验证。。。)。

上面使用了简单的2步就实现了一个XmlBeanFactory,我们也可以尝试去做做,例如:

ClassPathResource res = new ClassPathResource("beans.xml")

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);

reader.loadBeanDefinitions(res);

看看,是不是很简单!


最后,在《SPRING技术内幕》上说,下面的这个继承路线,是一条主要的BeanFactory的设计路径

    BeanFactory->HierarchicalBeanFactory->ConfigurableBeanFactory

看了一下,可能是因为就是上面的图画的一样,ConfigurableListableBeanFactory接口和AbstractAutowireCapableBeanFactory抽象类都实现了这个接口,所以说它是一条主要的设计路径吧。

Bean模块的接口就先介绍这些,接下来我们介绍ApplicationContext的相关接口和实现类,以及一些源码的介绍。


Context模块:

    这个模块中,非常重要的接口就是ApplicationContext接口。这个接口继承了BeanFactory接口,也就是说它也有管理Bean的功能。但他和BeanFactory有什么不同呢?它是在BeanFactory基础之上,又增加了国际化,容器事件(可以监听容器的一些事件,来做一些操作)等。

    下面介绍和ApplicationContext接口相关的一些接口。介绍之前,我们先看一下接口的关系图,有助于理解。



    - ApplicationEventPublisher
    - BeanFactory
    - EnvironmentCapable
    - HierarchicalBeanFactory
    - ListableBeanFactory
    - MessageSource
    - ResourceLoader
    - ResourcePatternResolver

    (BeanFactory,HierarchicalBeanFactory,ListableBeanFactory在前面已经介绍完了,就不在再介绍了)

ApplicationEventPublisher:

spring的事件发布者接口,定义了发布事件的接口方法publishEvent。因为ApplicationContext实现了该接口,因此spring的ApplicationContext实例具有发布事件的功能(publishEvent方法在AbstractApplicationContext中有实现)。在使用的时候,只需要把ApplicationEventPublisher的引用定义到ApplicationEventPublisherAware的实现中,spring容器会完成对ApplicationEventPublisher的注入。

下面是两个关于ApplicationEventPublisher的文章,有兴趣可以看一下:

    http://www.cnblogs.com/beenupper/archive/2012/12/01/2797303.html
    http://enjiex.iteye.com/blog/1070094

EnvironmentCapable:

是一个包含和暴露Enviroment引用的组件。所有的spring的application context都继承了EnvironmentCapable接口。

Enviroment是干什么用的呢?Environment包含两方便的抽象,profile和 property。profile的作用是,根据定义的profile,让哪一组Bean的定义生效,例如:用profile来定义不同环境的数据库连接。后者是提供方便的抽象,应用程序可以方便的访问 system property 环境变量自定义属性等。

关于Environment的文章,有兴趣可以看一下:http://blog.csdn.net/windsunmoon/article/details/45197361

MessageSource:

这个策略模式的接口(这个接口主要用于实现设置模式中的策略模式)是整个国际化消息支持的基础,它定义了国际化的主要接口。
关于之方面的文章,有兴趣可以看一下:http://book.51cto.com/art/201004/193394.htm

ResourceLoader:

这个策略模式的接口(这个接口主要用于实现设置模式中的策略模式)加载Resources。例如:ClassPathResource或FileSystemResources等。
关于Resoure,前面说了一点,Resource 接口是具体资源访问策略的抽象,也是所有资源访问类所实现的接口。Resource 接口主要提供了如下几个方法:
    getInputStream():定位并打开资源,返回资源对应的输入流。每次调用都返回新的输入流。调用者必须负责关闭输入流。
   exists():返回 Resource 所指向的资源是否存在。
    isOpen():返回资源文件是否打开,如果资源文件不能多次读取,每次读取结束应该显式关闭,以防止资源泄漏。
    getDescription():返回资源的描述信息,通常用于资源处理出错时输出该信息,通常是全限定文件名或实际 URL。
    getFile:返回资源对应的 File 对象。
    getURL:返回资源对应的 URL 对象。
从方法来看,这个接口主要定义了一些访问资源的方式,为了方便使用。功能强大的抽象类AbstractApplicationContext的基类DefaultResourceLoader,只实现了一个接口,就是这个接口。FileSystemXmlApplicationContext等实现类,都是从AbstractApplicationContext一点点继承过来的。

ResourcePatternResolver:

这个策略模式的接口(这个接口主要用于实现设置模式中的策略模式)用来把一个路径解析成Resources对象。这个接口继承了ResourceLoader接口,是ResourceLoader接口的一个扩展。它ResourceLoader接口相比,重载了一个方法getResources(String locationPattern),这个方法返回值是Resource数组(Resource[]),而ResourceLoader接口的返回值只是单个Resources。Spring提供了一个ResourcePatternResolver实现PathMatchingResourcePatternResolver(它提供了很多方法来添加和查找Resources),
它是基于模式匹配的,默认使用AntPathMatcher进行路径匹配,它除了支持ResourceLoader支持的前缀外,还额外支持“classpath*:”用于加载所有匹配的类路径Resource,ResourceLoader不支持前缀“classpath*:”:

介绍完上面的接口,我们就知道了ApplicationContext这个接口大概有什么功能了。


我们从FileSystemXmlApplicationContext再来看看接口的实现类,看看它都实现了哪些接口和实现类的功能大概是什么。
它的继承结构如下:
java.lang.Object
  org.springframework.core.io.DefaultResourceLoader
    org.springframework.context.support.AbstractApplicationContext
     org.springframework.context.support.AbstractRefreshableApplicationContext
      org.springframework.context.support.AbstractRefreshableConfigApplicationContext
       org.springframework.context.support.AbstractXmlApplicationContext
        org.springframework.context.support.FileSystemXmlApplicationContext


DefaultResourceLoader:

这个实现类,实现了ResourceLoader接口,说明这个实现类具有通过给定的路径加载Resource的功能。由此可见,ApplicationContext第一个实现类的功能,就是加载Resources功能。

AbstractApplicationContext:

这个实现类,继承了DefaultResourceLoader这个类,并且实现了ConfigurableApplicationContext接口。ConfigurableApplicationContext这个接口实现了ApplicationContext接口和Lifecycle、Closeable两个接口。既然它实现了ApplicationContext接口,也就说明它实现了上面讲的那些接口。所以AbstractApplicationContext实现类,算是一个核心实现类了。

AbstractRefreshableApplicationContext:

从名字可以看出来,主要实现了刷新Context内部的BeanFactory功能,通过refreshBeanFactory()方法。看了原代码可以看出,在AbstractApplicationContext类中,实现了“准备刷新,获取新BeanFactory,配置新的BeanFactory”等功能。但具体的实现细节没有被实现,还是抽象方法,就像refreshBeanFactory()方法,AbstractRefreshableApplicationContext类和GenericApplicationContext类都实现了这个抽象方法,做了不同的实现。这个类里有一个要被子类实现的抽象方法loadBeanDefinitions(DefaultListableBeanFactory beanFactory)。这个实现类没有实现其它接口。

AbstractRefreshableConfigApplicationContext:

它实现了BeanNameAware, InitializingBean这两个接口。从源代码可以看出,这个类主要作用是用来配置Resource的路径。这个方法在FileSystemXmlApplicationContext的构造函数中被调用。它配置路径的方法主要是和通过和Environment一起来解析路径。

AbstractXmlApplicationContext:这个类实现了读取XML类型的Resources。读取XML类型Resources,是使用了XmlBeanDefinitionReader,通过这个Reader来读取XML类型的Resources。这个实现类没有实现其它接口。

FileSystemXmlApplicationContext:基本的功能在基类上都已经实现了。这个类主要重写了getResourceByPath(String path) 方法,返回一个FileSystemResource类型的Resource。同样继承于AbstractXmlApplicationContext类的ClassPathXmlApplicationContext类,就没有实现这个方法,这是什么?这个方法最早是在DefaultResourceLoader定义的,在定义时默认就是使用了ClassPathContextResource做为返回Resource类型。这个实现类没有实现其它接口。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值