# Spring MVC V2 https://zhuanlan.zhihu.com/p/37886319 https://github.com/x213212/minispring * 修正jdk 動態代理改為 cglib * 修正 serlet controller 攔截不到 AOP 問題 草寫 https://github.com/x213212/minispring ![](https://i.imgur.com/fG8wO2u.png) ![](https://i.imgur.com/Caf90Le.png) ![](https://i.imgur.com/q6sFjwF.png) ![](https://i.imgur.com/aZLVTaK.png) ![](https://i.imgur.com/jrR2MbX.png) ![](https://i.imgur.com/s0ahkwL.png) ![](https://i.imgur.com/3oFzmhI.png) ![](https://i.imgur.com/PFldqsw.png) # Untils init 我首先先找出 ScanAOP 裡面所要代理的 目標 bean 和 method 再來就是 在 AOPMapping 取得子節點 BeanAopMapping 對 子節點 不需要動態代理 和 動態代理 bean 做替換 Switchbean 將 ioclist 父節點 換為 proxyioclist( Controller 攔截 aop) ``` public static void checkAnnotation() { //scan aop ScanAOP(ioclist); AOPMapping(proxyioclist); BeanAopMapping(ioclist); Switchbean(); } ``` # Untils.java ```java package com.spring.demo.utils; import com.spring.demo.anno.*; import com.spring.demo.anno.aop.*; import com.spring.demo.servlet.MyDispatcherServlet; import net.sf.cglib.proxy.Enhancer; import org.apache.catalina.Context; import org.apache.catalina.LifecycleException; import org.apache.catalina.startup.Tomcat; import javax.servlet.http.HttpServlet; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.*; public class UtilsScan { public static List<Map <String , Object>> ioclist = new ArrayList<>(); public static List<Map <String , Object>> proxyioclist = new ArrayList<>(); private Properties properties = new Properties(); private static Map<String, Method> handlerMapping = new HashMap<>(); private static Map<String, Object> controllerMap =new HashMap<>(); public UtilsScan() throws LifecycleException { UtilsScan.doScan(); java.io.File file = new java.io.File("." ); int port = 8080; Tomcat tomcat = new Tomcat(); tomcat.setBaseDir("temp"); tomcat.setPort(port); String contextPath = "/"; String docBase = file.getAbsolutePath(); Context context = tomcat.addContext(contextPath, docBase); HttpServlet servlet = new MyDispatcherServlet(handlerMapping,controllerMap); String servletName = "MyDispatcherServlet"; String urlPattern = "/*"; tomcat.addServlet(contextPath, servletName, servlet); context.addServletMappingDecoded(urlPattern, servletName); tomcat.start(); tomcat.getServer().await(); // ServletConfig tmp =this.getServletConfig(); // doLoadConfig(tmp.getInitParameter("contextConfigLocation")); // // UtilsScan.doScan(); } public static void doScan(){ String packagePath = "D:\\Programming\\spring\\minispringcore\\minispring\\src\\main\\java\\com\\spring\\demo"; File file = new File (packagePath ); String[] childFile = file.list(); for (String fileName : childFile) { System.out.println(fileName); File childfiletmp = new File( packagePath +"\\" +fileName); String classFileName[] = childfiletmp.list(); for (String className : classFileName ){ if(className.equals("aop") || className.equals("run") || className.equals("MyDispatcherServlet") ) continue; className = className.substring(0,className.indexOf(".")); Object object = null; try { System.out.println("com.spring." + fileName +"." + className); Class classtmp = Class.forName("com.spring.demo." + fileName +"." + className); if(classtmp.isAnnotationPresent(ComponentTest.class)) { object = classtmp.newInstance(); Map<String , Object> map= new HashMap<>(); map.put(classtmp.getSimpleName() , object); ioclist.add(map); // System.out.println( "ADD ComponentTest 註解 :"+object.getClass().getSimpleName()+"object :" +object); } } catch(InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } System.out.println("ioclist hash map : "+ioclist); /* Autowired */ checkAnnotation(); initHandlerMapping(); } private void doLoadConfig(String location){ //把web.xml中的contextConfigLocation对应value值的文件加载到流里面 InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(location); try { //用Properties文件加载文件里的内容 properties.load(resourceAsStream); } catch (IOException e) { e.printStackTrace(); }finally { //关流 if(null!=resourceAsStream){ try { resourceAsStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } private static void initHandlerMapping(){ if(ioclist.isEmpty()){ return; } try { for (Map <String , Object> annotations: ioclist ){ for ( String annotationkv : annotations.keySet()){ Object tempObject = annotations.get(annotationkv); Class tempClass = tempObject.getClass() ; ComponentTest[] tempType = (ComponentTest[]) tempClass.getAnnotationsByType(ComponentTest.class); String tempClassType=null; String baseUrl =""; try { tempClassType = tempType[0].value()[0]; System.out.println(tempType[0].value()[0]); } catch ( Exception e){ tempClass = tempObject.getClass().getSuperclass(); tempType = (ComponentTest[]) tempClass.getAnnotationsByType(ComponentTest.class); tempClassType =tempType[0].value()[0]; } if (tempClassType.equals("Controller") ) { MyRequestMapping[] tempType2 = (MyRequestMapping[]) tempClass.getAnnotationsByType(MyRequestMapping.class); baseUrl = tempType2[0].value(); Method[] methods = tempClass.getMethods(); for (Method method : methods) { if(!method.isAnnotationPresent(MyRequestMapping.class)){ continue; } MyRequestMapping annotation = method.getAnnotation(MyRequestMapping.class); String url = annotation.value(); url =(baseUrl+"/"+url).replaceAll("/+", "/"); handlerMapping.put(url,method); controllerMap.put(url,tempObject); System.out.println(url+","+method); } } } } } catch (Exception e) { e.printStackTrace(); } } public static List<Map <String , Object>> BeanAopMapping( List<Map <String , Object>> master) { List<Map<String, Object>> tmp = new ArrayList<>() ; for (Map<String, Object> annotations : master) { for (String annotationkv : annotations.keySet()) { Object tempObject = annotations.get(annotationkv); Class tempClass = tempObject.getClass(); ComponentTest[] tempType = (ComponentTest[]) tempClass.getAnnotationsByType(ComponentTest.class); String tempClassType = null; try { tempClassType = tempType[0].value()[0]; System.out.println(tempType[0].value()[0]); } catch (Exception e) { tempClassType = ""; } if (tempClassType.equals("Default") || tempClassType.equals("") || tempClassType.equals("Controller") ) { Field[] fields = tempClass.getDeclaredFields(); if (fields.length >0 ) { for (Field tempfield : fields) { // System.out.println(tempfield.getType() +"2112"); if (tempfield.isAnnotationPresent(Autowired.class)) { String targetName = tempfield.getType().getSimpleName(); for (Map<String, Object> annotationchilds : ioclist) { for (String annotationchildkv : annotationchilds.keySet()) { if (annotationchilds.get(annotationchildkv).getClass().getSimpleName().equals(targetName)) { // && 'annotationchildkv.equals(targetName)' tempfield.setAccessible(true); try { Map<String, Object> map = new HashMap<>(); map.put(targetName, annotationchilds.get(targetName)); // int k =0; boolean find = false; for (Map<String, Object> proxyio : proxyioclist) { for (String proxyiokv : proxyio.keySet()) { if(proxyiokv.equals(targetName)){ tempfield.set(tempObject, proxyio.get(targetName)); find =true; // proxyioclist.remove(k); break; } k++; } } if(find == false) { tempfield.set(tempObject, annotationchilds.get(targetName)); } tmp.add(map); BeanAopMapping(tmp); } catch (IllegalAccessException e) { e.printStackTrace(); } break; } } } } } } else return tmp; } } } return master; } public static List<Map <String , Object>> ScanAOP( List<Map <String , Object>> master) { List<Map<String, Object>> tmp = new ArrayList<>() ; for (Map <String , Object> annotations: master ){ for ( String annotationkv : annotations.keySet()){ Object tempObject = annotations.get(annotationkv); Class tempClass = tempObject.getClass(); ComponentTest[] tempType = (ComponentTest[]) tempClass.getAnnotationsByType(ComponentTest.class); String tempClassType=null; try { tempClassType = tempType[0].value()[0]; System.out.println(tempType[0].value()[0]); } catch ( Exception e){ tempClassType =""; } if( tempClassType.equals("Aspect")) { Method[] Methods = tempClass.getMethods(); for (Method method : Methods) { List<Map <String , Object>> methodlist = new ArrayList<>(); Before[] filters = null; if(method.getAnnotationsByType(Before.class).length >0){ filters = method.getAnnotationsByType(Before.class); Advice2 AfterAdvice = null; for (Before filter : filters) { for (int i = 0; i < filter.value().length; i++) { System.out.println(filter.value()[i]); } try { for (Map<String, Object> annotations2 : ioclist) { for (String annotationkv2 : annotations2.keySet()) { Object tempObject2 = annotations2.get(annotationkv2); Class tempClass2 = tempObject2.getClass(); if (tempClass2.getName().equals(filter.value()[0].toString())) { Method aopmethod = tempClass.getMethod(filter.value()[1].toString(), null); Map<String, Object> map = new HashMap<>(); // Map<Object, Object> map2 = new HashMap<>(); Advice2 handler = new BeforeAdvice2(tempObject2, aopmethod,null, tempObject); Object f = Enhancer.create(tempClass2, handler); //map.put(tempClass2.getSimpleName(), f); map.put(tempClass2.getSimpleName(), f); //map2.put(tempObject2, aopmethod); // methodlist.add( map2); proxyioclist.add(map); tmp.add(map); // ScanAOP(tmp); break; } //ScanAOP(tmp); } } } catch (NoSuchMethodException e) { e.printStackTrace(); } } } } } } } return master; } public static List<Map <String , Object>> AOPMapping (List<Map <String , Object>> master) { List<Map <String , Object>> tmp = new ArrayList<>() ; for( int s = 0 ; s < master.size();s ++){ Set set =((HashMap) master.get(s)).entrySet(); Iterator i =set.iterator(); // Display elements while(i.hasNext()) { Map.Entry me = (Map.Entry)i.next(); System.out.print(me.getKey() + ": "); if(me.getValue()!= null) if( me.getValue().getClass().getSuperclass().getDeclaredFields().length >0 ){ Map <String , Object> tst = new HashMap<>(); Field[] fields = me.getValue().getClass().getSuperclass().getDeclaredFields(); for (Field tempfield : fields) { String targetName = tempfield.getType().getSimpleName(); for (Map<String, Object> annotationchilds : proxyioclist) { if ( annotationchilds.keySet().contains(targetName) ){ tempfield.setAccessible(true); try { Map<String, Object> map = new HashMap<>(); map.put( targetName, annotationchilds.get(targetName)); tempfield.set(me.getValue(), annotationchilds.get(targetName)); tmp.add(map); } catch (IllegalAccessException e) { e.printStackTrace(); } break; } } } } } } return master; } public static void Switchbean(){ for(int i = 0 ; i <ioclist.size() ; i++) for(int j = 0 ; j <proxyioclist.size() ; j++){ if(ioclist.get(i).keySet().toString().equals(proxyioclist.get(j).keySet().toString()) ){ ioclist.set(i,proxyioclist.get(j)); break; } } } public static void checkAnnotation() { //scan aop ScanAOP(ioclist); AOPMapping(proxyioclist); BeanAopMapping(ioclist); Switchbean(); } /** * 把字符串的首字母小写 * @param name * @return */ private String toLowerFirstWord(String name){ char[] charArray = name.toCharArray(); charArray[0] += 32; return String.valueOf(charArray); } public static Object getProxy(Object bean, Advice advice) { return Proxy.newProxyInstance(UtilsScan.class.getClassLoader(), bean.getClass().getInterfaces(), advice); } public static Object getProxy2(Object bean, Advice advice) { return Proxy.newProxyInstance(UtilsScan.class.getClassLoader(), bean.getClass().getInterfaces(), advice); } } ``` # aop advice預計拓展為 ```Java public class BeforeAdvice2 implements Advice2 { private Object bean; private Object o; private Method methodInvocation; private Method BeforeMethodInvocation; private Method AfterMethodInvocation; private Object original; public BeforeAdvice2(Object bean,Method BeforeMethodInvocation , Method AfterMethodInvocation, Object test ) { this.bean = bean; this.methodInvocation = methodInvocation; this.BeforeMethodInvocation = BeforeMethodInvocation; this.AfterMethodInvocation = AfterMethodInvocation; this.o = test; } @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { // System.out.println("BEFORE"); // methodInvocation.invoke(o,null); //methodInvocation.invoke(this.o,null); if(BeforeMethodInvocation != null) BeforeMethodInvocation.invoke(this.o,null); Object result = method.invoke(bean, args); if(AfterMethodInvocation != null) AfterMethodInvocation.invoke(this.o,null); // System.out.println(method.getName()); // method.invoke(o, null); // System.out.println("AFTER"); return result; } } ``` 手寫 aop 或許可以用來拓展 手寫 mybatis (?