03.SpringMVC之器
整体结构介绍
在Servlet的继承结构中一共有5个类,GenericServlet和HttpServlet在java中剩下的三个类HttpServletBean、FrameworkServlet和DispatcherServlet是SpringMVC中的这三个类直接实现三个接口:EnvironmentCapable、EnvironmentAware和ApplicationContextAware。
XXXAware在spring里表示对XXX可以感知,通俗点解释就是:如果在某个类里面想要使用spring的一些东西,就可以通过实现XXXAware接口告诉spring,spring看到后就会给你送过来,而接收的方式是通过实现接口唯一的方法setXXX,比如,有一个类想要使用当前的ApplicationContext,那么我们只需要让它实现ApplicationContextAware接口,然后实现接口中唯一的方法,void setApplicationContext(ApplicationContext applicationContext(会自动传过来,直接用))就可以了,spring会自动调用这个方法将applicationContext传给我们,我们只需要接收就可以了。
EnvironmentCapable,顾名思义,当然就是具有Environment的能力,也就是可以提供Environment,所以EnvironmentCapable唯一的方法是Environment getEnvironment(),用于实现EnvironmentCapable接口的类,就是告诉spring它可以提供Environment,当spring需要Environment的时候就会调用其getEnvironment方法跟它要
HttpServletBean
在HttpServletBean的init方法中,首先将Servlet中配置的参数使用BeanWrapper设置到DispatcherServlet的相关属性,然后调用模板方法initServletBean,子类就通过这个方法初始化
public final void init() throws ServletException { // 1. 操作配置文件里的属性 PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(),this.requiredProperties); if (!pvs.isEmpty()) { try { // 2.获取目标对象的beanwrapper对象 BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); // 空实现 initBeanWrapper(bw); bw.setPropertyValues(pvs, true); }catch (BeansException ex) { throw ex; } } // 空方法 让子类实现 initServletBean(); }
BeanWrapper是Spring 提供的一个用来操作JavaBean属性的工具,使用它可以直接修改一个对象的属性
public class User{ String userName; //省略get和set方法 } public class BeanWrapperTest{ psvm{ User user = new User(); BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(user); bw.setPropertyValue("userName","张三"); sout(user.getUserName()); PropertyValue value = new PropertyValue("userName","李四"); sout(user.getUserName()); } }
FrameworkServlet
FrameworkServlet继承HttpServletBean,FrameworkServlet的初始化入口方法是initServletBean
// org.springframework.web.servlet.FrameworkServlet protected final void initServletBean() throws ServletException{ //初始化WebApplicationContext this.webApplicationContext = initWebApplicationContext(); //模板方法,子类可以覆盖在里面做一些初始化的工作 initFrameworkServlet(); } protected WebApplicationContext initWebApplicationContext(){ //获取rootContext WebApplicationContext rootContext = WebApplicationContextUtils.getApplictionContext(getServletContext()); WebApplicationContext wac = null; //如果已经通过构造方法设置了webApplicationContext if(this.webApplicationContext != null){ wac = this.webApplicationContext; if(wac instanceof ConfigurableWebApplicationContext){ ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext ) wac; if(!cwac.isActive()){ if(cwac.getParent() == null){ cwac.setParent(rootContext); } configureAndRefreshWebApplicationContext(cwac) } } } if(wac == null){ //当webApplicationContext已经存在ServletContext中时,通过配置在Servlet中的contextAttribute参数获取 wac = findWebApplicationContext(); } if(wac == null)[ //如果webApplicationContext还没有创建,则创建一个 wac = createWebApplicationContext(rootContext); } if(!this.refreshEventReceived){ //当ContextRefreshedEvent事件没有触发时调用此方法,模板方法,可以在子类重写 onRefresh(wac); } if(this.publicContext){ //将ApplicationContext保存到ServletContext中 String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName,wac); } return wac; }
这个initWebApplicationContext方法做了三件事
1.获取spring的根容器rootContext
获取根容器的原理是,默认情况下spring会将自己的容器设置成ServletContext属性,默认根容器的key为org.springframework.web.context.WebApplicationContext.ROOT,所以获取根容器只需要调用ServletContext的getAttribute就可以了
2.设置webApplicationContext并根据情况调用onRefresh方法
3.将webApplicationContext设置到ServletContext中
DispatcherServlet
OnRefresh方法是DispathcerServlet的入口方法,OnRefresh中简单地调用了initStrategis,在initStrategies中调用了9个初始化方法
//org.springframework.web.servlet.DispatcherServlet protected void onRefresh (ApplicationContext context){ initStrategies(context); } protected void initStrategies(Application context){ initMultipartResolver(context); initLocalResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
原文地址:https://www.cnblogs.com/deityjian/p/11494345.html
- JS魔法堂:jsDeferred源码剖析
- JavaSE(八)之集合概述
- 浅谈PHP开发与Java开发的优劣势,还不知道学习方向的可以来看看
- KVM+Qemu+Libvirt实战
- 内核级虚拟化技术
- tomcat配置ROOT目录和多站点
- IntelliJ IDEA使用(一)基本设置与类、方法模板设置
- JS魔法堂:从void 0 === undefined说起
- Maven(三)在Eclipse中使用Maven与Maven坐标
- Nginx多站点设置及负载均衡
- Maven(二)Maven项目的创建(命令、myeclipse)及生命周期
- JS魔法堂:初探传说中的setImmediate函数
- 配置nginx.conf实现负载均衡
- Maven(一)初识Maven
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- CephFS 介绍及使用经验分享
- CephFS源码分析
- linux cache介绍及控制
- Lustre文件系统安装
- Lustre参数调整
- samba源码安装及调试
- 设计模式实战-状态模式,让代码更清爽简洁
- 改善深层神经网络——吴恩达深度学习课程笔记(二)
- Spring Boot 监听 Redis Key 失效事件实现定时任务,超时订单自动关闭绝佳实现
- TensorFlow的核心概念:张量和计算图
- 四连问:API 接口应该如何设计?如何保证安全?如何签名?如何防重?
- TensorFlow基础:创建计算图
- TensorFlow基础:常量
- 如何在Python中优雅地使用进度条?
- 绝了!这款工具让SpringBoot不再需要Controller、Service、DAO、Mapper!