讲道理,感觉自己有点菜。Spring 源码看不懂,不想强行解释,等多积累些项目经验之后再看吧,但是 Spring 中的控制反转(IOC)和面向切面编程(AOP)思想很重要,为了更好的使用 Spring 框架,有必要理解这两个点,为此,我使用 JDK API 实现了一个玩具级的简陋 IOC/AOP 框架 mini-spring,话不多说,直接开干。
环境搭建&快速使用全部代码已上传 GitHub:https://github.com/czwbig/mini-spring
将代码弄到本地并使用 IDE 打开,这里我们用 IDEA;
使用 Gradle 构建项目,可以使用 IDEA 提供的 GUI 操作,也可以直接使用 gradle build 命令;
如下图,右击 mini-spring\framework_use_test\build\libs\framework_use_test-1.0-SNAPSHOT.jar ,点击 Run,当然也可以直接使用 java -jar jarPath.jar 命令来运行此 jar 包;
浏览器打开 localhost:8080/rap 即可观察到显示 CXK 字母,同时 IDE 控制台会输出:
first,singing <chicken is too beautiful>. and the chicken monster is dancing now. CXK rapping... oh! Don't forget my favorite basketball.下面开始框架的讲解。
简介本项目使用 Java API 以及内嵌 Tomcat 服务器写了一个玩具级 IOC/AOP web 框架。实现了 @Controller、@AutoWired、@Component 、@Pointcut、@Aspect、@Before、@After 等 Spring 常用注解。可实现简单的访问 uri 映射,控制反转以及不侵入原代码的面向切面编程。
讲解代码实现之前,假设读者已经掌握了基础的项目构建、反射、注解,以及 JDK 动态代理知识,项目精简,注释详细,并且总代码 + 注释不足 1000 行,适合用来学习。其中构建工具 Gradle 没用过也不要紧,我也是第一次使用,当成没有 xml 的 Maven 来看就行,下面我会详细解读其构建配置文件。
模块组成项目由两个模块组成,一个是框架本身的模块,实现了框架的 IOC/AOP 等功能,如下图:
类比较多,但是大部分都是代码很少的,特别是注解定义接口,不要怕。
aop 包中是 After 等注解的定义接口,以及动态代理辅助类;
bean 包中是两个注解定义,以及 BeanFactory 这个 Bean 工厂,其中包含了类扫描和 Bean 的初始化的代码;
core 包是一个 ClassScanner 类扫描工具类;
starter 包是一个框架的启动与初始化类;
web/handler 包中是 uri 请求的处理器的收集与管理,如查找 @Controller 注解修饰的类中的 @RequestMapping 注解修饰的方法,用来响应对应 uri 请求。
web/mvc 包定义了与 webMVC 有关的三个注解;
web/server 包中是一个嵌入式 Tomcat 服务器的初始化类;
web/servlet 包中是一个请求分发器,重写的 service() 方法定义使用哪个请求处理器来响应浏览器请求;
另一个模块是用来测试(使用)框架的模块,如下图:
就像我们使用 Spring 框架一样,定义 Controller 等来响应请求,代码很简单,就不解释了。
项目构建根目录下有 setting.gradle、build.gradle 项目构建文件,其中 setting.gradle 指定了项目名以及模块名。
rootProject.name = 'mini-spring' include 'framework' include 'framework_use_test'build.gradle 是项目构建设置,主要代码如下:
plugins { id 'java' } group 'com.caozhihu.spring' version '1.0-SNAPSHOT' sourceCompatibility = 1.8 repositories { repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } } // mavenCentral() } dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' }引入了 gradle 的 java 插件,因为 gradle 不仅仅可以用于 java 项目,也可以用于其他项目,引入了 java 插件定义了项目的文件目录结构等。
然后就是项目的版本以及 java 源代码适配级别,这里是 JDK 1.8,在后面是指定了依赖仓库,gradle 可以直接使用 maven 仓库。
最后就是引入项目具体依赖,这里和 maven 一样。
每个模块也有单独的 build.gradle 文件来指定模块的构建设置,这里以 framework_use_test 模块的 build.gradle 文件来说明:
dependencies { // 只在单元测试时候引入此依赖 testCompile group: 'junit', name: 'junit', version: '4.12' // 项目依赖 compile(project(':framework')) } jar { manifest { attributes "Main-Class": "com.caozhihu.spring.Application" } // 固定打包句式 from { configurations.runtime.asFileTree.files.collect { zipTree(it) } } }除去和项目根目录下构建文件相同部分,其他的构建代码如上,这里的 dependencies 除了添加 Junit 单元测试依赖之外,还指定了 framework 模块。