spring MVC執行過程分析與原始碼實現
spring mvc 啟動過程可分為如下3步:
============================================= web.xml DispatcherServlet Spring MVC總入口 1、配置階段 配置初始化引數 classpathapplication.xml 配置了無數個bean /*.json
Init方法 被web容器呼叫,如tomcat 載入application.xml內容 掃描相關聯的class 根據使用者配置的包名,用list存下來 2、初始化階段 IOC容器初始化 就是一個map, beanId 例項 依賴注入DI 如果宣告類中定義了成員變數,而且需要賦值 初始化一個HandlerMapping 將URL和contral類中某一個方法進行關聯,儲存到一個map中
service方法 doget/dopost 呼叫一個doDispatch方法 根據URL去匹配已經初始化完畢的HandleMapping中的method 3、執行階段 通過反射機制,動態呼叫 通過Respons輸出
簡易原始碼實現過程如下:
package spring; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Field; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties;
import javax.servlet.ServletConfig; import javax.servlet.http.HttpServlet; import javax.servlet.http.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.sound.midi.ControllerEventListener;
import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry.Entry; import com.sun.jmx.remote.util.Service;
import com.sun.org.apache.xml.internal.security.Init;
public class guoDispacherServlet extends HttpServlet{ private Properties p = new Properties(); private List<String> classNames = new ArrayList<String>(); private Map<String, Object> ioc = new HashMap<String, Object>(); private void Init(ServletConfig config) throws javax.servlet.ServletException { //1.載入配置檔案 doloadConfig(config.getInitParameter("contextConfiglocation")); //2.掃描所有相關類 doScanner(p.getProperty("scanPackeage")); //3.初始化所有class相關例項,並且儲存到IOC容器中 doInstance(); //4.自動化的依賴注入 doAutowired(); //5.初始化HandlerMapping initHandlerMapping(); System.out.println("初始化成功!"); } private void initHandlerMapping() { // TODO Auto-generated method stub } private void doAutowired() { if(ioc.isEmpty()){ return; } for(java.util.Map.Entry<String, Object> entry:ioc.entrySet()){ Field[] fields = entry.getValue().getClass().getDeclaredFields(); for(Field field: fields){ if(!field.isAnnotationPresent(Autowried.class)){ continue; }else{ Autowried autoweried field.getAnnotation(Autowried.class); } } } } private void doInstance() { if(classNames.isEmpty()){ return; } for(String className:classNames){ Class<?> clazz = Class.forName(className); //進行例項化 if(clazz.isAnnotationPresent(Service.class)){ String beanName = lowerFirst(clazz.getSimpleName()); ioc.put(beanName, clazz.newInstance()); }else if(clazz.isAnnotationPresent(ControllerEventListener.class)){ }else{ continue; } } } private void doScanner( String packageName) { URL url = this.getClass().getClassLoader().getResource("/"+packageName.replaceAll("\\.", "/")); File classerDir = new File(url.getFile()); for(File file:classerDir.listFiles()){ if(file.isDirectory()){ doScanner(packageName+"."+file.getName()); }else{ String className = packageName+"."+file.getName().replace(".class",""); classNames.add(className); } } } private void doloadConfig(String location) { InputStream is = this.getClass().getClassLoader().getResourceAsStream(location); p.load(is); } //字串首字母變小寫函式 private String lowerFirst(String str){ char[] chars = str.toCharArray(); chars[0] +=32; return String.valueOf(chars); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws javax.servlet.ServletException, IOException { // TODO Auto-generated method stub super.doGet(req, resp); }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws javax.servlet.ServletException, IOException { // TODO Auto-generated method stub super.doPost(req, resp); doDispatch(); }
private void doDispatch() { // TODO Auto-generated method stub } @Override protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws javax.servlet.ServletException, IOException { // TODO Auto-generated method stub super.service(arg0, arg1); } }