自己实现spring核心功能 一
聊聊spring
spring对于java开发者来说,是最熟悉不过的框架了,我们日常开发中每天都在使用它。它有着各种各样的好处,简单易用,得心应手... ...
我们一说到spring就会讲到ioc 、aop、依赖注入,注解等专业名词,不少刚接触java的人,都是一头雾水,很难直观的去理解这些是个什么玩意,但使用的多了 就爱上了它给我们带来的便利。
探索spring
当我们熟练的使用它之后就会好奇,ioc怎么实现的呢?为什么我只要在类的变量中加入@AutoWrited 就能使用这个变量?带着疑惑我们就会开始翻源码,找答案。经过一番努力,最终我们定位到了spring-context.jar包,找到了
- AbstractApplicationContext对象的refresh方法,这里面的实现和步骤,就是整个spring功能的核心,里面的实现另我们叹为观止,但也相当之复杂,用到了很大设计模式,难以窥见全貌,很多地方的设计我们不知道为啥需要这么实现。但我们还是知道了ioc容器实际上是用的Hashmap,
依赖注入使用的是反射,aop实际上是动态代理完成的。还有很大一部分代码看的有点晕,就是加强健壮性保证生命周期和各种特性的。不管怎么说,那都是别人的东西,我们只会用,源码我们看了很多,但很少自己来实现出来。
spring实现分析
不管怎么说,别人的实现是别人的,自己写出来的东西是属于我们自己的。既然下决心要自己也能实现了,那我们就需要分析分析了。
spring怎么做到代码侵入量少且各层级分明的呢?
spring采用约定大于配置,按照固定模式,层级分为Controller 、Service、Component、Bean、Configuration来标识类型
spring是怎么管理依赖关系的?
是通过注解或xml
spring是怎么发现哪些类需要管理的?
是注解标记+包路径扫描
spring是如何实现依赖注入的?
通过AutoWrited注解标记加反射实例化对象
spring是如何管理Bean的?
使用HashMap容器、Set容器实现单例Bean
spring怎么实现aop切面的呢?
使用动态代理的方式,并提供了cglib和jdk默认实现两种方式
spring是在何时加载到内存中的呢?
springMvc是通过web.xml配置入口触发,springboot是通过springApplication初始化触发
本次实现spring核心功能会涉及到哪些点?
1.注解的定义与使用
2.容器的初始化
3.配置文件的读取与使用
4.sevlet的使用
5.注解的定义与使用
6.反射的运用
7.url路由与方法映射
8.参数解析与绑定
9.正则与转义
正式开始
首先创建一个maven项目,代码结构如下:
添加jar包依赖:
里面有2个jar包加一个插件
- javax.servlet-api.jar 用来启动核心代码和处理请求
- fastjson.jar 用来做json参数绑定
- jetty-maven-plugin 使用jetty作为web容器启动
- 完整maven代码如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.honstat</groupId>
- <artifactId>test-spring</artifactId>
- <version>1.0-SNAPSHOT</version>
- <dependencies>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>4.0.1</version>
- </dependency>
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>fastjson</artifactId>
- <version>1.2.56</version>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-maven-plugin</artifactId>
- <version>9.4.5.v20170502</version>
- <configuration>
- <scanIntervalSeconds>10</scanIntervalSeconds>
- <webApp>
- <contextPath>/</contextPath>
- </webApp>
- <httpConnector>
- <port>8080</port>
- </httpConnector>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </project>
创建前端控制器类
前端控制器专门处理servlet请求,匹配到对应的方法执行后返回,前端控制器是什么可以参考我的另一篇博客《SpringMvc请求处理流程与源码探秘》
这里我们创建一个叫CJDispatcherServlet的类,它继承HttpServlet类,并且重写HttpServlet的init(),doGet(),doPost() 这3个方法,图中的HomeService和StudentService可以先忽略不写
配置web.xml
需要配置<servlet> 和<servlet-mapping> 2个标签
<servlet>中需要
1.指定servlet名称
2.指定处理请求的前端控制器类
3.设置初始化配置文件路径
完整web.xml文件如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
- version="2.5">
- <servlet>
- <servlet-name>cjservletMVC</servlet-name>
- <servlet-class>com.honstat.spring.service.CJDispatcherServlet</servlet-class>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>spring/application.properties</param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>cjservletMVC</servlet-name>
- <url-pattern>/*</url-pattern>
- </servlet-mapping>
- </web-app>
添加注解
我们知道,spring里面是通过给类加注解来识别各种使用场景的,那我们就来实现几个必用的
作用在类上的:
JCController
JCService
JCComponent
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- public @interface JCController {
- String value() default "";
- }
全部采用这种类型
作用在方法上和类上的:
JCRequestMapping
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.TYPE,ElementType.METHOD})
- public @interface JCRequestMapping {
- String value() default "";
- }
作用在字段上的:
JCAutoWrited
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.FIELD)
- public @interface JCAutoWrited {
- String value() default "";
- }
到此我们已经初步的创建完了需要准备的类,准备工作告一段落。
由于篇幅有限,下一篇开始实现核心功能了!
自己实现spring核心功能 一的更多相关文章
- Spring 核心功能演示
Spring 核心功能演示 Spring Framework 简称 Spring,是 Java 开发中最常用的框架,地位仅次于 Java API,就连近几年比较流行的微服务框架 SpringBoot, ...
- 自己实现spring核心功能 三
前言 前两篇已经基本实现了spring的核心功能,下面讲到的参数绑定是属于springMvc的范畴了.本篇主要将请求到servlet后怎么去做映射和处理.首先来看一看dispatherServlet的 ...
- 自己实现spring核心功能 二
前言 上一篇我们讲了spring的一些特点并且分析了需要实现哪些功能,已经把准备工作都做完了,这一篇我们开始实现具体功能. 容器加载过程 我们知道,在spring中refesh()方法做了很多初始化的 ...
- spring 核心
1 Spring 1.1 专业术语了解 1.1.1 组件/框架设计 侵入式设计 引入了框架,对现有的类的结构有影响:即需要实现或继承某些特定类. 例如: Struts框架 非侵入式设计 引入了 ...
- 读源码之Spring 核心内容
为什么有这篇文档 工作两三年之后,总感觉什么东西都懂,但是什么东西又都不会.所以日常学习是很有必要的,俗话说学而不思则罔 ,思而不学则殆.所以我们要学思结合,学习的方法有很多,但是思考的深度或者说有没 ...
- Spring框架的IOC核心功能快速入门
2. 步骤一:下载Spring框架的开发包 * 官网:http://spring.io/ * 下载地址:http://repo.springsource.org/libs-release-local/ ...
- Spring 框架的核心功能之AOP技术
1. AOP 的概述 AOP, Aspect Oriented Programming, 面向切面编程; 通过预编译方式和运行期动态代理实现程序功能的统一维护的技术; AOP 采取横向抽取机制,取代了 ...
- Spring框架的核心功能之AOP技术
技术分析之Spring框架的核心功能之AOP技术 AOP的概述 1. 什么是AOP的技术? * 在软件业,AOP为Aspect Oriented Programming的 ...
- 第一章 spring核心概念
一.Spring作用:管理项目中各种业务Bean(service类.Dao类.Action类),实例化类,属性赋值 二.Spring IOC(Inversion of Control )控制反转,也被 ...
随机推荐
- android_sdcard读写(三)
这次来个稍微复杂点的. package cn.com.sxp;import android.app.Activity;import android.app.ProgressDialog;import ...
- 无法在<fastCGI>应用程序配置中找到<handler> scriptProcessor
在打开php文件的时候发现iis7.5报错了 每次在切换php版本的时候不知道为什么会出现这个错误,有的时候就又不会报错直接可以正常使用,然而php版本确定已经下载好,才可能的打开这个页面,那么就是i ...
- k8s学习 - 概念 - ReplicaSet
k8s学习 - 概念 - ReplicaSet 首先,ReplicaSet 和 ReplicationController 基本上一样,除了上篇说到的selector有不同之外,没有啥区别.(官网也是 ...
- 什么是常量?变量? if语句介绍
1.python 的历史 2004 年 Django 的产生 phyton2与 python3 的区别 Python2:源码不统一,有重复的代码功能 Python3:源码统一,没有有重复的代码功能 2 ...
- ListView在ScrollView中不显示全部的问题
在实际应用中,我们可能会遇到把ListView放到ScrollView中的情况,在这种情况下,ListView的滑动属性与ScrollView的滑动出现冲突,从而ListView只显示一项.这里提供一 ...
- Docker 环境下搭建nexus私服
一.安装docker 1.脚本安装 本机环境CentOS7,用户为root 下载脚本到工作目录 curl -fsSL https://get.docker.com -o get-docker.sh 执 ...
- MySql的数据库优化到底优啥了都??(2)
嘟嘟在写此篇文章之前心里先默念(简单,通俗,工整)*10 吟唱完了,进入正题 3.Memory存储引擎 除了存放一个表结构相关信息的.frm文件在磁盘上,其他数据都存储在内存中.说白点哪天你数据库死机 ...
- C#3.0新增功能03 隐式类型本地变量
连载目录 [已更新最新开发文章,点击查看详细] 从 Visual C# 3.0 开始,在方法范围内声明的变量可以具有隐式“类型”var. 隐式类型本地变量为强类型,就像用户已经自行声明该类型,但 ...
- fjnu2016-2017 低程 PROBLEM B 捧杯
#include <iostream>#include <cmath>using namespace std; int _gcd(int x,int y){ return y= ...
- luogu题解 P3388 【【模板】割点(割顶)】
外加定义:在一个无向图中,如果删掉点 x 后图的连通块数量增加,则称点 x 为图的割点. 外加图示 开始思路为割桥上的点为割点,后来证明的确正确. 不过可惜的是他的逆定理错了(gg了),不过数据很弱以 ...