- HttpServletBean继承关系及说明
[说明]一个传统的web应用都是从web.xml开始的.对于SpringMVC来说,我们需要在web.xml中配置一个DispatcherServlet作为前端控制器并为其制定一些初始参数,DispatcherServlet本质上还是一个servlet,只是多了一些和SpringMVC框架有关的一些功能.
HttpServletBean继承自HttpServlet,因此Web容器启动时将调用HttpServletBean的init()方法. - init()方法详解
public final void init() throws ServletException {
// 1. 操作配置文件里的属性
PropertyValues pvs = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);
if (!pvs.isEmpty()) {
try {
// 2.获取目标对象的beanwrapper对象
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment()));
this.initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
} catch (BeansException var4) {
if (this.logger.isErrorEnabled()) {
this.logger.error("Failed to set bean properties on servlet '" + this.getServletName() + "'", var4);
}
throw var4;
}
}
this.initServletBean();
}
1)作用:映射此servlet的配置属性到bean属性上并且调用子类初始化
2.1
/**
* Create new ServletConfigPropertyValues.
* @param config ServletConfig we'll use to take PropertyValues from
* @param requiredProperties set of property names we need, where
* we can't accept default values
* @throws ServletException if any required properties are missing
*/
public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties)
throws ServletException {
Set<String> missingProps = (!CollectionUtils.isEmpty(requiredProperties) ?
new HashSet<>(requiredProperties) : null);
// 1. 获取web.xml里springmvc的属性
Enumeration<String> paramNames = config.getInitParameterNames();
while (paramNames.hasMoreElements()) {
// 标签名称 web.xml 里的 <param-name>
String property = paramNames.nextElement();
// 标签值 web.xml 里的 <param-value>
Object value = config.getInitParameter(property);
// 2.将上面获取到的key-value封装进 perpertyValue 对象
addPropertyValue(new PropertyValue(property, value));
if (missingProps != null) {
missingProps.remove(property);
}
}
// Fail if we are still missing properties.
if (!CollectionUtils.isEmpty(missingProps)) {
throw new ServletException(
"Initialization from ServletConfig for servlet '" + config.getServletName() +
"' failed; the following required properties were missing: " +
StringUtils.collectionToDelimitedString(missingProps, ", "));
}
}
[注] ServletConfig就是servlet的配置对象,通过他可以获取到web.xml里的参数
2.2
/**
* Add a PropertyValue object, replacing any existing one for the
* corresponding property or getting merged with it (if applicable).
* @param pv PropertyValue object to add
* @return this in order to allow for adding multiple property values in a chain
*/
public MutablePropertyValues addPropertyValue(PropertyValue pv) {
for (int i = 0; i < this.propertyValueList.size(); i++) {
PropertyValue currentPv = this.propertyValueList.get(i);
// 如果有name是一样的
if (currentPv.getName().equals(pv.getName())) {
// 判断到底采用哪一个
pv = mergeIfRequired(pv, currentPv);
// 把值再设置上
setPropertyValueAt(pv, i);
return this;
}
}
// 如果不存在name一样 就直接添加到集合中
this.propertyValueList.add(pv);
return this;
}
总结:
以上就是获取到web.xml中springmvc中的初始化参数后设置到MutablePropertyValues中的 propertyValueList中,如果发生name重复就根据Mergeable 类再次判断采用哪一个值
2.3 创建BeanWrapper
1)BeanWrapper, 它提供分析和操作标准 JavaBeans的操作:获取和设置属性值、获取属性描述符以及查询属性的可读性/可写性的能力。
2)获取servletContext的资源加载器 ,然后通过beanWrapper初始化编辑器,把PropertyValues装进当前对象
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*: *-dispatcher-servlet.xml
</param-value></init-param>
上面参数的名字和值就会作为一个PropertyVaule存放在ServletConfigPropertyValues中,通过bw.setPropertyValues(pvs, true)方法被set到被包裹者实例的相应的属性中, 在这里就是DispatcherServlet的contextConfigLocation中。