Spring MVC V2

https://zhuanlan.zhihu.com/p/37886319
https://github.com/x213212/minispring







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

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預計拓展為

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 (?