春天的故事1

环境搭建

Spring应该是目前在java企业级开发中使用最广泛的一个框架了,甚至已经可以说是java企业级开发的一个事实上的标准,它为解决企业级开发的复杂性提供了丰富的功能,所以,深入了解这个框架,并且做到知其然并知其所以然是非常有必要的,而阅读源码则是一个捷径。

Spring的源码使用Gradle构建,并且版本4之后使用的java8的特性,所以需要在计算机上安装1.8版本的java环境及Gradle的构建工具。

Gradle是一个类似maven的构建工具,他是用了Groovy来编辑构建脚本,他可以从https://gradle.org/现在,约60多mb,下载后放到指定位置,配置环境变量即可。

Spring的源码存放的地址为Spring-Framework,可使用git命令进行下载:

git clone https://github.com/spring-projects/spring-framework.git

下载完成后不能直接打开,不过好在有一个帮助文档,我是使用的IntelliJ IDEA来打开的,好在提供了一个Idea导入的帮助文档:

通过里边的内容可知,首先需进行预编译,即打开cmd,到spring源码的目录后输入:

gradlew.bat cleanIdea :spring-oxm:compileTestJava

需要进行漫长的等待,我的计算机使用了大概20多分钟:

然后使用idea导入项目,选择gradle项目即可,导入后的目录如下:

好,下面让我们来开启一段春天的旅行。

旅行开启

学习Spring,当然要从最简单最核心的Bean开始,这是一个非常简单的例子,甚至它比官网的类还要简单,首先是一个Bean定义:

@Component
public class TestBean {
    private String testStr="Hello World";
    public String getTestStr(){
        return testStr;
    }
    public void setTestStr(String testStr){
        this.testStr=testStr;
    }
}

这个bean没有任何的特别之处,的确,这也是符合Spring框架的基本原则之一:

使用基本的POJO进行轻量级和最小侵入式的开发。

如果说这个类还有和普通JavaBean的不同之处,那就是Component注解了,它用来声明这是一个组件类,即对Bean的声明。甚至这个注解也可以省略,但是我实在不喜欢又臭又长的xml文件,所以,至少对于Spring的业务配置来说,我还是只考虑注解配置。

接下来就是一个配置类:

@Configuration
@ComponentScan
public class BeanFactoryTest {
    public static void main(String []args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(BeanFactoryTest.class);
        TestBean tb = ac.getBean("testBean", TestBean.class);
        System.out.println(tb.getTestStr());
    }
}

好了,你可能觉得太简单,可能觉得还有什么更加看上去复杂,高大上的东西,但是,很遗憾,真没了,Spring的一个入门实例已经结束,试着运行一下:

很明显,这是一个一目了然的代码,如果不报错,那么输出一定会是testStr的值,即"Hello World"

在项目中,使用BeanFactory接口的情况并不多见,至少我一次都没见过,一般来说大多数使用的都是他的子接口ApplicationContext,这里只是用于测试。

不管对于这个小例子有多么的不屑,他都是一个对于Spring框架的使用案例,并且也可以算是实现了Bean的使用与创建的解耦。
下面让我们分析一下这个框架为我们完成了什么工作,我想,对于Java语言有一定基础的人,一定可以猜出来,他完成功能也就无非是以下几点:

  1. 获取配置类
  2. 扫描基础包内所有的组件(无参数表示以配置类所在的包为基础包)
  3. 找到组件后,以类名首字母小写的形式命名并保存
  4. 根据名字获取对应类的实例
  5. 调用实例

即如果仅仅从功能实现的方面来考虑,仅仅两个类就足够了,即:

  1. 反射工具类(注解操作类):查询并保存所有的组件,并进行反射实例化
  2. AppContext类:用于对反射工具类的操作串联。

如果是真的是这样,那么这就是一个人人都可以写出来的操作工具库,但是,作为一个已经成为企业级开发事实上标准的优秀框架来说,真的是这么简单么?

内容梳理

为了回答这个问题,我们先从第一个实例化的类开始:

AnnotationConfigApplicationContext

通常,对于Spring这种优秀的代码,梳理清楚它的继承结构和聚合结构,对于类也就可以称得上完全理解,下面是他的继承结构图:

看上去很复杂,我们先看一下代码中的返回接口,即:

ApplicationContext接口

从类图中可以看出,ApplicationContext是Spring的Context的顶级父类,他继承的几个类分别为:

  • BeanFactory:Spring容器访问的根接口,定义了以各种方式获取bean及bean的各种属性
  • ListableBeanFactory:扩展了BeanFactory,定义容器内Bean可枚举列表
  • HierarchicalBeanFactory:扩展了BeanFactory,定义容器内Bean可分层继承
  • ResourceLoader:定义资源读取策略的接口
  • ResourcePatternResolver:通过各种条件匹配资源
  • MessageSource:定义了对消息处理的方法
  • ApplicationEventPublisher:定义了事件发布的功能
  • EnvironmentCapable:定义确定环境的功能
  • ApplicationContext:之上几个接口的综合,即确定环境,发布事件,以及读取资源和操作Bean的功能

注:
BeanFactory及实现是一个典型的工厂模式
ApplicationEventPublisher 使用了Java8的一个新特性,即FunctionalInterface注解,可否认为是混合模式?

弄清楚ApplicationContext的功能,这一块基本就明白了大半,ApplicationContext的直接子接口为ConfigurableApplicationContext,

他的继承关系为:

  • Lifecycle:定义了Spring对象的生命周期,即Start和Stop方法
  • Closeable:定义了数据或资源的释放或销毁方法
  • ConfigurableApplicationContext:配置和管理ApplicationContext,并提供对其进行管理的工具

好,到了这里,舞台已经准备好,那么,作为一场演出,还剩下什么呢?当然是演员了,到了这里,我们的演员(Bean)才姗姗来迟

下面把剩余的几个类简单介绍一下,下一章着重介绍还在拿大牌的演员,Bean

  • AliasRegistry:定义对alias的各种操作
  • ResourceLoader:定义资源读取策略的接口
  • DefaultResourceLoader:资源获取接口(ResourceLoader)的一个默认实现
  • AnnotationConfigRegistry:定义应用上下文的注解配置的功用接口,提供注册一个注解类和扫描包方法的定义
  • AbstractApplicationContext:通过模板方法模式对ApplicationContext接口进行一个抽象的实现,并不指定配置的类型。
  • BeanDefinitionRegistry:定义对BeanDefinition的各种增删改的操作(BeanDefinition用来描述一个Bean实例)
  • GenericApplicationContext:一个通用的应用实现,其他的实现一般继承此类
  • AnnotationConfigApplicationContext:综上功能,基于注解配置的应用实现
posted @ 2017-07-20 23:27  双鱼座的牛  阅读(275)  评论(0编辑  收藏  举报