在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的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继承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; }
获取根容器的原理是,默认情况下spring会将自己的容器设置成ServletContext属性,默认根容器的key为org.springframework.web.context.WebApplicationContext.ROOT,所以获取根容器只需要调用ServletContext的getAttribute就可以了
//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