环境搭建
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语言有一定基础的人,一定可以猜出来,他完成功能也就无非是以下几点:
- 获取配置类
- 扫描基础包内所有的组件(无参数表示以配置类所在的包为基础包)
- 找到组件后,以类名首字母小写的形式命名并保存
- 根据名字获取对应类的实例
- 调用实例
即如果仅仅从功能实现的方面来考虑,仅仅两个类就足够了,即:
- 反射工具类(注解操作类):查询并保存所有的组件,并进行反射实例化
- 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:综上功能,基于注解配置的应用实现