Spring源码-------手写体验MVC
目录
1、前言
本篇博客并非是对spring的原理进行深入的研究,而是通过模拟实现springmvc的功能来体验spring框架的强大之处。那么这篇博客涉及到的知识点大致有以下几点:
- 如何自定义注解,如何通过反射机制去赋予注解强大的功能(说白了,就是体验在反射机制下,注解功能是多么的强大)
- Spring Ioc容器的实现原理
- Spring DI 注解注入
- Java反射机制
- Java I/O流(加载配置文件,读取配置文件信息)
2、Spring实现MVC的基本思路
从下图可以大概知道,对于springmvc的实现大致分为三个阶段:配置阶段、初始化阶段、运行阶段。
配置阶段:
- 配置web.xml文件
- 设定init-param参数
- 设定url-pattern规则
- 配置Annotation注解
初始化阶段:
- 调用Servlet init()方法
- 加载配置文件
- 扫描相关的类
- IoC容器初始化,创建实例化对象(反射机制)并保存至容器
- 进行DI操作,扫描IoC容器中的实例,进行属性自动赋值
- 初始化HandlerMapping,将一个URL和一个Method进行一对一的关联映射
运行阶段:
- 调用doPost()/doGet()方法,获得Request/Response对象
- 匹配HandlerMapping,从request对象中获得用户输入的url找到对应的method
- 反射调用method.invoke()方法并返回结果
- response.getWriter().writer(),将返回结果输出到浏览器
3、实现MVC核心代码
3.1 首先建立一个Maven工程,然后引入相关的依赖和相关的配置,比如web.xml,application.properties等配置文件
大致结构如下:具体项目代码连接:
3.2 自定义注解和控制器和服务层
(1)注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ZPSAutowired {
String value() default "";
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ZPSController {
String value() default "";
}
@Target({ElementType.TYPE , ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ZPSRequestMapping {
String value() default "";
}
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ZPSRequestParam {
String value() default "";
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ZPSService {
String value() default "";
}
(2)service层
public interface DemoService {
String getMsg(String msg);
}
/**
* @description: 服务
* @author: zps
* @create: 2020-05-07 15:51
**/
@ZPSService
public class DemoImp implements DemoService {
@Override
public String getMsg(String msg) {
return "==========="+ msg + "==============";
}
}
(3)控制层
/**
* @description: 测试控制
* @author: zps
* @create: 2020-05-07 15:53
**/
@ZPSController
@ZPSRequestMapping("/test")
public class DemoController {
@ZPSAutowired
private DemoService demoService;
@ZPSRequestMapping("/add")
public void add(HttpServletRequest req, HttpServletResponse resp,
@ZPSRequestParam("a") Integer a, @ZPSRequestParam("b") Integer b){
try {
resp.getWriter().write(a + "+" + b + "=" + (a + b));
} catch (IOException e) {
e.printStackTrace();
}
}
@ZPSRequestMapping("/hello")
public String test(){
return demoService.getMsg("Success!");
}
}