bean是Spring 最核心的东西,打个比方,假设Spring是一个水桶,那么bean就是水桶里的水,水桶离开水后,就没啥作用了。我们先来看一下bean的定义:

 public class Person {
 private String name;
 private int age;

 public String getName() {
 return name;
 }

 public void setName(String name) {
 this.name = name;
 }

 public int getAge() {
 return age;
 }

 public void setAge(int age) {
 this.age = age;
 }

 public void info() {
 System.out.println("name:" + getName() + " age:" + getAge());
 }
 }

bean

这个bean 很普通?没错,Spring追求的是使我们的bean变成一个纯粹的POJO。

接下来看一下配置文件:

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns="http://www.springframework.org/schema/beans"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
     <bean id="person" class="com.juin.entity.Person">
         <property name="name" value="xingoo"/>
         <property name="age" value="12"/>
     </bean>
 </beans>

bean.xml

在上面的配置文件中,我们看到了bean的声明方式。尽管Spring中的bean 有N多属性来支撑我们业务中的各种应用,但是只要我们声明成这样,那么一般都可以满足。下面就是测试代码啦:

 public class Test {

     public static void main(String[] args) {
         // TODO Auto-generated method stub
         ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");// 读取bean.xml中的内容
         Person p = ctx.getBean("person", Person.class);// 创建bean的引用对象
         p.info();
     }

 }

Test

相信聪明的人,应该能猜到 控制台里将会打印  name:xingoo age:12  了。

好了,到这里,我们又复习了一遍Spring,我相信很多人对此都感到不屑吧!哈哈,那你们想知道这个过程具体是如何实现的吗?那就要好好理解Spring内部的原理了。由于Spring是一个开源的框架,所以我们研究起来很方便,只要上网拉份源码下来,就可以来啃啦!我也是第一次读源码吧,为了让自己坚持下去,就计划没读一点,就逼着自己写一篇博客,这样能让自己更加与动力一点吧!接下来我们开始吧!

我们先来分析一下上面的测试代码:ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");

这段测试代码无非就是分为三个步骤:

1.读取bean.xml文件;

2.根据bean.xml的配置信息找到对应的类的配置并实例化;

3.调用实例化的实例;

为了更清楚地描述,请看下图:

ConfigReader:用于读取和验证配置文件。我们要用配置文件里面的东西,当然首先要做的是读取,然后放置在内存中。

ReflectionUtil:用于根据配置文件中的配置文件进行反射实例化。比如上面的bean.xml中的<bean id="person" class="com.juin.entity.Person"/>,我们就可以根据bean.Person进行实例化。

App:用于完成整个逻辑的串联。

按照原始的思维方式,整个过程无非如此,但是作为一个风靡世界的优秀源码真的这么简单吗?答案当然是否定的。不妨一起来看看Spring的源码吧,用于实现上面功能的是org.Springframework.beans.jar。

这个是gradle管理的,如果想用eclipse打开,可以安装一个gradle进行转换。

在开始分析源码之前,我们必须先来熟悉下Spring两个最核心的类:DefaultListableBeanFactory和XmlBeanDefinitionReader。

1.DefaultListableBeanFactory

XmlBeanFactory继承自DefaultListableBeanFactory,而DefaultListableBeanFactory是整个bean加载的核心部分,是Spring注册和加载bean的默认实现,而对于XmlBeanFactory与DefaultListableBeanFactory的不同之处在于XmlBeanFactory中使用了自定义的XML读取器XmlBeanDefinitionReader,实现了个性化的BeanDefinitionReader读取,DefaultListableBeanFactory继承了AbstractAutowireCapableBeanFactory并实现了ConfigurableListableBeanFactory以及BeanDefinitionRegistry接口。下面是ConfigurableListableBeanFactory的层次结构图以及相关类图。

我先简单说一下上图中各类的作用吧:

1.AliasRegistry:定义对alias的简单增删改等操作。

2.SimpleAliasRegistry:主要使用map作为alias的缓存,并对接口AliasRegistry进行实现。

3.SingletonBeanRegistry:定义对单例的注册和获取。

4.BeanFactory:定义获取bean以及bean的各种属性。

5.DefaultSingletonBeanRegistry:对接口SingletonBeanRegistry各函数的实现。

6.HierarchicalBeanFactory:继承BeanFactory,也就是在BeanFactory定义的功能的基础上增加了对parentFactory的支持。

7.BeanDefinitionRegistry:定义对BeanDefinition的各种增删改操作。

8.FactoryBeanRegistrySupport:在DefaultSingletonBeanRegistry基础上增加了对FactoryBean的特殊处理功能。

9.ConfigurableBeanFactory:根据配置Factory的各种方法。

10.ListableBeanFactory:根据各种条件获取bean的配置清单。

11.AbstractBeanFactory:综合FactoryBeanRegistrySupport和ConfigurableBeanFactory的功能。

12.AutowireCapableBeanFactory:提供创建bean,自动注入,初始化以及应用bean的后处理器。

13.AbstractAutowireCapableBeanFactory:综合AbstractBeanFactory并对接口AutowireCapableBeanFactory进行实现。

14.ConfigurableListableBeanFactory:BeanFactory配置清单,指定忽略类型以及接口等。

15.DefaultListableBeanFactory:综合上面所有功能,主要是对Bean注册后的处理。

XmlBeanFactory对DefaultListableBeanFactory类进行了扩展,主要用于从XML文档中读取BeanDefinition,对于注册以及获取Bean都是使用从父类DefaultListableBeanFactory继承的方法去实现,而纬度与父类不同的个性化实现就是增加了XmlBeanDefinitionReader类型的reader属性。在XmlBeanFactory中主要使用reader属性对资源文件进行读取和注册。

2.XmlBeanDefinitionReader

XML配置文件的读取是Spring中重要的功能,因为Spring的大部分功能都是以配置作为切入点的,那么我们可以从XmlBeanDefinitionReader中梳理一下资源文件读取,解析以及注册的大致脉络,首先我们可以看看各个类的功能。

1.ResourceLoader:定义资源加载器,主要用于根据给定的资源文件地址返回对应的Resource。

2.BeanDefinitionReader:主要定义资源文件读取并转换为BeanDefinition的各个功能。

3.EnvironmentCapable:定义获取Environment方法。

4.DocumentLoader:定义从资源文件加载到转换为Document的功能。

5.AbstractBeanDefinitionReader:对EnvironmentCapable,BeanDefinitionReader类定义的功能的实现。

6.BeanDefinitionDocumentReader:定义读取Document并注册BeanDefinition功能。

7.BeanDefinitionParserDelegate:定义解析Element的各种方法。

通过上图我们可以知道XmlBeanDefinitionReader主要包括以下几步的处理:

(1)通过继承自AbstractBeanDefinitionReader中的方法,来使用ResourceLoader将资源文件路径转换为对应的Resource文件。

(2)通过DocumentLoader对Resource文件进行转换,将Resource文件转换为Document文件。

(3)通过实现接口BeanDefinitionDocumentReader的DefaultBeanDefinitionDocumentReader类对Document进行解析,并使用BeanDefinitionParserDelegate对Element进行解析。

3.容器的基础XmlBeanFactory

到这里,我们已经对Spring的容器功能有了一个大致的了解。接下来我们会详细探索每个步骤的实现。接下来要深入分析以下功能的代码实现:

BeanFactory bf = new XmlBeanFactory(new ClassPathResource(bean.xml));

首先调用ClassPathResource的构造函数来构造Resource资源文件的实例对象,这样后续的资源处理就可以用Resource提供的各种服务来操作了,当我们有了Rssource后就可以进行XmlBeanFactory的初始化了。那么Resource资源是如何封装的呢?请看下一章节,

Spring:容器基本用法的更多相关文章

  1. 7 -- Spring的基本用法 -- 9...容器中Bean的生命周期

    7.9 容器中Bean的生命周期 Spring可以管理singleton作用域的Bean的生命周期,Spring可以精确地知道该Bean何时被创建,何时被初始化完成.容器何时准备销毁该Bean实例. ...

  2. 7 -- Spring的基本用法 -- 8... 抽象Bean与子Bean;Bean继承与Java继承的区别;容器中的工厂Bean;获得Bean本身的id;强制初始化Bean

    7.8 深入理解容器中的Bean 7.8.1 抽象Bean与子Bean 把多个<bean.../>配置中相同的信息提取出来,集中成配置模版------这个配置模版并不是真正的Bean,因此 ...

  3. 7 -- Spring的基本用法 -- 5... Spring容器中的Bean;容器中Bean的作用域;配置依赖;

    7.5 Spring容器中的Bean 7.5.1 Bean的基本定义和Bean别名 <beans.../>元素是Spring配置文件的根元素,该元素可以指定如下属性: default-la ...

  4. 7 -- Spring的基本用法 -- 4... 使用 Spring 容器:Spring 容器BeanFactory、ApplicationContext;ApplicationContext 的国际化支持;ApplicationContext 的事件机制;让Bean获取Spring容器;Spring容器中的Bean

    7.4 使用 Spring 容器 Spring 有两个核心接口:BeanFactory 和 ApplicationContext,其中ApplicationContext 是 BeanFactory ...

  5. 整合Servlet到Spring容器

    有时在Spring(3.2.5)项目中,如果使用到Servlet,可能希望Servlet实例作为bean受Spring容器管理,这样也能自动注入其他需要的bean,查了下,发现只针对过滤器提供了代理类 ...

  6. 【Spring】Junit加载Spring容器作单元测试

    如果我们需要对我们的Service方法作单元测试,恰好又是用Spring作为IOC容器的,我们可以这么配置Junit加载Spring容器,方便做单元测试. > 基本的搭建 (1)引入所需的包 & ...

  7. 普通Java类获取spring 容器的bean的5种方法

    方法一:在初始化时保存ApplicationContext对象方法二:通过Spring提供的工具类获取ApplicationContext对象方法三:继承自抽象类ApplicationObjectSu ...

  8. 自己动手写spring容器(3)

    好久没有写博客了,今天闲下来将之前未完成的表达出来. 在之前的文章自己动手写spring容器(2)中完成了对spring的依赖注入的实现,这篇将会介绍spring基于注解的依赖注入的实现. 在一般的J ...

  9. spring深入学习(三)-----spring容器内幕

    之前都是说了怎么配置bean以及用法之类的,这篇博文来介绍下spring容器内幕. 内部容器工作机制 Spring中AbstractApplicationContext抽象类的refresh()方法是 ...

  10. 获取Spring容器Bean对象工具类

    在开发中,总是能碰到用注解注入不了Spring容器里面bean对象的问题.为了解决这个问题,我们需要一个工具类来直接获取Spring容器中的bean.因此就写了这个工具类,在此记录一下,方便后续查阅. ...

随机推荐

  1. [LeetCode] Rabbits in Forest 森林里的兔子

    In a forest, each rabbit has some color. Some subset of rabbits (possibly all of them) tell you how ...

  2. ide phpStorm常用代码片段设置

    1.打开设置(File -> Settings) 2.如图 3 . 最后,在PHP文件中输入 ll 并按 TAB 即可打出代码块

  3. shell 爬取图片下载到本地

    #!/bin/bash #ddmm // #if [ -z $string ] 如果string 为空 #-z STRING the length of STRING is zero read -p ...

  4. 如何组织AxTOCControl里面的数据

    如何组织AxTOCControl里面的数据,实际上是组织AXMapControl的数据,将添加的数据进行整理.代码在最后面. 思路参考自: https://blog.csdn.net/u0124887 ...

  5. 【C++】括号匹配

    #include<iostream> #include<cstring> #include<cstdlib> #include<queue> using ...

  6. 解决loadrunner录制时 Request Connection: Remote Server @ 0.0.0.0:80 (Service=?) NOT PROXIED! (REASON: Unable to connect to remote server: rc = -1 , le = 0)问题

    环境为win7+ie8+loadrunner11,录制脚本回放查看Recoding log 出现如下错误:[Net An. Error    ( 7f8:1340)] Request Connecti ...

  7. Linux 磁盘介绍(磁盘、分区、MBR、GPT)

    原文:https://www.linuxidc.com/Linux/2013-06/85717.htm 1. CHS(Cylinder-Head-Sector): was an early metho ...

  8. LG1081 开车旅行

    题意 城市\(i\)的海拔高度为\(H_i\)(各不相同).定义距离为海拔差的绝对值 小\(A\)和小\(B\)轮流开车.从\(S\)起,一直向东行驶. 小\(A\)会选择第二近的城市作为目的地.小\ ...

  9. centos下etcd集群安装

    先仔细了解学习etcd 官方: https://github.com/etcd-io/etcd https://www.cnblogs.com/softidea/p/6517959.html http ...

  10. Java博客目录

    JavaWeb 1.Tomcat使用 2.Servlet入门 3.JSP&EL&JSTL 4.Listener&Filter Java框架 Hibernate 1.简介及初使用 ...