Skip to content

Latest commit

 

History

History
918 lines (791 loc) · 33.3 KB

02.用300行代码手写提炼Spring的核心原理.md

File metadata and controls

918 lines (791 loc) · 33.3 KB

Spring源码

image-20211012231434744

Spring 实现V1

public class STDispatchServlet extends HttpServlet {
    private static final long serialVersionUID = 823658696654581429L;

    // 保存配置文件
    private final Properties contextConfig = new Properties();

    // 保存类名
    private final List<String> classNames = new ArrayList<String>();

    // ioc容器,暂时不考虑ConcurrentHashMap
    private final Map<String, Object> ioc = new HashMap<String, Object>();

    // 保存url和method的对应关系
    private final Map<String, Object> handlerMapping = new HashMap<String, Object>();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 6.调用
        try {
            doDispatch(req, resp);
        } catch (Exception exception) {
            exception.printStackTrace();
            resp.getWriter().write("500 Exception, Detail :" + Arrays.toString(exception.getStackTrace()));
        }
        super.doPost(req, resp);
    }

    private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        String url = req.getRequestURI();
        String contextPath = req.getContextPath();
        url = url.replaceAll(contextPath, "").replaceAll("/+", "/");
        if (this.handlerMapping.containsKey(url)) {
            resp.getWriter().write("404 Not Found!");
            return;
        }
        Method method = (Method) this.handlerMapping.get(url);
        // 通过反射拿到method的class,在拿到class的名称
        // 在调用toLowerFirstCase 获得beanName
        String beanName = toLowerFirstCase(method.getDeclaringClass().getSimpleName());

        // 暂时写死
        Map<String, String[]> params = req.getParameterMap();
        method.invoke(ioc.get(beanName), new Object[]{req, resp, params.get("name")[0]});
    }

    @Override
    public void init(ServletConfig config) throws ServletException {

        // 1.加载配置文件
        doLoadConfig(config.getInitParameter("contextConfigLocation"));

        // 2.扫描相关的类
        doScanner(contextConfig.getProperty("scanPackage"));

        // 3.初始化扫描到的类,并将他们放入到IOC容器中
        doInstance();

        // 4.完成依赖注入
        doAutowired();

        // 5.初始化handlerMapping
        initHandlerMapping();

        System.out.println("ST Spring Framework");

        super.init(config);
    }

    // 加载配置文件
    private void doLoadConfig(String contextConfigLocation) {
        InputStream fis = null;
        // 从类路径下找到spring主配置文件
        // 并且将其读取出来放到Properties对象中
        // 把scanPackage=cn.simplethinking.springframwork读到内存中
        fis = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
        try {
            contextConfig.load(fis);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != fis) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 扫描出类
    private void doScanner(String scanPackage) {
        // 包路径
        // 转为文件路径,实际上把.换成/就可以了
        URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
        File classPath = new File(url.getFile());
        for (File file: classPath.listFiles()) {
            if (file.isDirectory()) {
                doScanner(scanPackage + "." + file);
            } else {
                if (file.getName().endsWith(".class")) {
                    continue;
                }
                String className = (scanPackage + "." + file.getName().replace(".class", ""));
                classNames.add(className);
            }
        }
    }

    private void doInstance() {
        // 初始化,为DI准备
        if (classNames.isEmpty()) {return;}
        try {
            for (String className : classNames) {
                Class<?> clazz = Class.forName(className);
                // 什么样的类才要初始化
                // 加了注解的类c才需要初始化
                // 为了简化代码逻辑,只简化@Controller、@Service
                if (clazz.isAnnotationPresent(STController.class)
                        || clazz.isAnnotationPresent(STService.class)) {
                    Object instance = clazz.newInstance();
                    // key: className 首字母小写
                    // Spring 默认首字母小写
                    String beanName = toLowerFirstCase(clazz.getSimpleName());
                    ioc.put(beanName, instance);
                } else if (clazz.isAnnotationPresent(STService.class)) {
                    // 1.自定义beanName
                    STService stService = clazz.getAnnotation(STService.class);
                    String beanName = stService.value();
                    // 2.默认首字母小写
                    if ("".equals(beanName.trim())) {
                        beanName = toLowerFirstCase(clazz.getSimpleName());
                    }
                    Object instance = clazz.newInstance();
                    ioc.put(beanName, instance);
                    // 3.根据类型自动赋值
                    for (Class<?> i : clazz.getInterfaces()) {
                        if (ioc.containsKey(i.getName())) {
                            throw new Exception("The ”" +  i.getName()  + " “is exist");
                        }
                        ioc.put(i.getName(), instance);
                    }

                } else {
                    continue;
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    /**
     * 默认不存在类名首字母小写的情况
     * @param simpleName
     * @return
     */
    private String toLowerFirstCase(String simpleName) {
        char[] chars = simpleName.toCharArray();
        // 之所以加32,是因为大小写字母恶ASCII码相差32
        // 而且大写字母的ASCII码小于小写字母的ASCII码
        // 在Java中,对char作算学运算,实际上就是对ASCII码做运算
        chars[0] += 32;
        return String.valueOf(chars);
    }

    private void doAutowired() {
        if (ioc.isEmpty()) {
            return;
        }
        for (Map.Entry<String, Object> entry : ioc.entrySet()) {
            // Declared
            Field[] fields = entry.getValue().getClass().getDeclaredFields();
            for (Field field : fields) {
                if (!field.isAnnotationPresent(STAutowired.class)) {
                    continue;
                }

                STAutowired autowired = field.getAnnotation(STAutowired.class);

                // 如果用户没有自定义beanName,默认根据类型注入
                String beanName = autowired.value().trim();
                if ("".equals(beanName)) {
                    beanName = field.getType().getName();
                }
                field.setAccessible(true);
                try {
                    // 用反射机制动态赋值
                    field.set(entry.getValue(), ioc.get(beanName));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            
        }
    }

    private void initHandlerMapping() {
        if (ioc.isEmpty()) {
            return;
        }

        for (Map.Entry<String, Object> entry : ioc.entrySet()) {
            Class<?> clazz = entry.getValue().getClass();
            if (!clazz.isAnnotationPresent(STController.class)) {
                continue;
            }
            // 类上面的url
            String baseUrl = "";
            if (clazz.isAnnotationPresent(STRequestMapping.class)) {
                STRequestMapping mapping = clazz.getAnnotation(STRequestMapping.class);
                baseUrl = mapping.value();
            }

            // 默认获取所有的public方法
            for (Method method : clazz.getMethods()) {
                if (!method.isAnnotationPresent(STRequestMapping.class)) {
                    continue;
                }
                STRequestMapping requestMapping = method.getAnnotation(STRequestMapping.class);

                // 优化
                String url = ("/" + (baseUrl) + "/" + requestMapping.value()).replaceAll("/+", "/");

                handlerMapping.put(url, method);
                System.out.println("Mapped :" + url + "," + method);
            }
        }
    }
}

Spring实现 V2

public class STDispatchServlet extends HttpServlet {
    private static final long serialVersionUID = 823658696654581429L;

    // 保存配置文件
    private final Properties contextConfig = new Properties();

    // 保存类名
    private final List<String> classNames = new ArrayList<String>();

    // ioc容器,暂时不考虑ConcurrentHashMap
    private final Map<String, Object> ioc = new HashMap<String, Object>();

    // 保存url和method的对应关系
    private final Map<String, Object> handlerMapping = new HashMap<String, Object>();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 6.调用
        try {
            doDispatch(req, resp);
        } catch (Exception exception) {
            exception.printStackTrace();
            resp.getWriter().write("500 Exception, Detail :" + Arrays.toString(exception.getStackTrace()));
        }
        super.doPost(req, resp);
    }

    private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        String url = req.getRequestURI();
        String contextPath = req.getContextPath();
        url = url.replaceAll(contextPath, "").replaceAll("/+", "/");
        if (this.handlerMapping.containsKey(url)) {
            resp.getWriter().write("404 Not Found!");
            return;
        }
        Method method = (Method) this.handlerMapping.get(url);
        // 通过反射拿到method的class,在拿到class的名称
        // 在调用toLowerFirstCase 获得beanName

        // 暂时写死
        // 从request中拿到url传过来的参数
        Map<String, String[]> params = req.getParameterMap();

        //获取形参列表
        Class<?>[] parameterTypes = method.getParameterTypes();

        Object[] paramValues = new Object[parameterTypes.length];
        for (int i = 0; i < parameterTypes.length; i++) {
            Class parameterType = parameterTypes[i];
            if (parameterType == HttpServletRequest.class) {
                paramValues[i] = req;
                continue;
            } else if (parameterType == HttpServletResponse.class) {
                paramValues[i] = resp;
                continue;
            }
            // 把方法上的注解拿到,得到一个二维数组
            Annotation[][] pa =  method.getParameterAnnotations();
            for (int j = 0; j < pa.length; j++) {
                // 我们要 解析的只是 STRequestParam
                for (Annotation a : pa[j]) {
                    if (a instanceof STRequestParam) {
                        // 拿到参数的名称,方便去url去匹配
                        String paramName = ((STRequestParam) a).value();
                        if (params.containsKey(paramName)) {
                            for (Map.Entry<String, String[]> param : params.entrySet()) {
                                // 拿到key所对应的值,这个值是一对多的关系
                                // 一个key对应一个数组
                                // 而对方接受的String类型
                                // 类型的强制转化
                                String value = Arrays.toString(param.getValue()).replaceAll("\\[|\\]]", "")
                                        .replaceAll("\\s", "");
                                paramValues[i] = convert(parameterType, value);
                            }
                        }
                    }
                }
            }
        }
        String beanName = toLowerFirstCase(method.getDeclaringClass().getSimpleName());
        method.invoke(ioc.get(beanName), new Object[]{req, resp, params.get("name")[0]});
    }

    // url传过来的参数都是String,HTTP时基于字符串的协议
    private Object convert(Class<?> type, String value) {
        if (Integer.class == type) {
            return Integer.valueOf(value);
        }
        // 如果还有double还要加if
        return value;
    }

    @Override
    public void init(ServletConfig config) throws ServletException {

        // 1.加载配置文件
        doLoadConfig(config.getInitParameter("contextConfigLocation"));

        // 2.扫描相关的类
        doScanner(contextConfig.getProperty("scanPackage"));

        // 3.初始化扫描到的类,并将他们放入到IOC容器中
        doInstance();

        // 4.完成依赖注入
        doAutowired();

        // 5.初始化handlerMapping
        initHandlerMapping();

        System.out.println("ST Spring Framework");

        super.init(config);
    }

    // 加载配置文件
    private void doLoadConfig(String contextConfigLocation) {
        InputStream fis = null;
        // 从类路径下找到spring主配置文件
        // 并且将其读取出来放到Properties对象中
        // 把scanPackage=cn.simplethinking.springframwork读到内存中
        fis = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
        try {
            contextConfig.load(fis);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != fis) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 扫描出类
    private void doScanner(String scanPackage) {
        // 包路径
        // 转为文件路径,实际上把.换成/就可以了
        URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
        File classPath = new File(url.getFile());
        for (File file: classPath.listFiles()) {
            if (file.isDirectory()) {
                doScanner(scanPackage + "." + file);
            } else {
                if (file.getName().endsWith(".class")) {
                    continue;
                }
                String className = (scanPackage + "." + file.getName().replace(".class", ""));
                classNames.add(className);
            }
        }
    }

    private void doInstance() {
        // 初始化,为DI准备
        if (classNames.isEmpty()) {return;}
        try {
            for (String className : classNames) {
                Class<?> clazz = Class.forName(className);
                // 什么样的类才要初始化
                // 加了注解的类c才需要初始化
                // 为了简化代码逻辑,只简化@Controller、@Service
                if (clazz.isAnnotationPresent(STController.class)
                        || clazz.isAnnotationPresent(STService.class)) {
                    Object instance = clazz.newInstance();
                    // key: className 首字母小写
                    // Spring 默认首字母小写
                    String beanName = toLowerFirstCase(clazz.getSimpleName());
                    ioc.put(beanName, instance);
                } else if (clazz.isAnnotationPresent(STService.class)) {
                    // 1.自定义beanName
                    STService stService = clazz.getAnnotation(STService.class);
                    String beanName = stService.value();
                    // 2.默认首字母小写
                    if ("".equals(beanName.trim())) {
                        beanName = toLowerFirstCase(clazz.getSimpleName());
                    }
                    Object instance = clazz.newInstance();
                    ioc.put(beanName, instance);
                    // 3.根据类型自动赋值
                    for (Class<?> i : clazz.getInterfaces()) {
                        if (ioc.containsKey(i.getName())) {
                            throw new Exception("The ”" +  i.getName()  + " “is exist");
                        }
                        ioc.put(i.getName(), instance);
                    }
                } else {
                    continue;
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    /**
     * 默认不存在类名首字母小写的情况
     * @param simpleName
     * @return
     */
    private String toLowerFirstCase(String simpleName) {
        char[] chars = simpleName.toCharArray();
        // 之所以加32,是因为大小写字母恶ASCII码相差32
        // 而且大写字母的ASCII码小于小写字母的ASCII码
        // 在Java中,对char作算学运算,实际上就是对ASCII码做运算
        chars[0] += 32;
        return String.valueOf(chars);
    }

    private void doAutowired() {
        if (ioc.isEmpty()) {
            return;
        }
        for (Map.Entry<String, Object> entry : ioc.entrySet()) {
            // Declared
            Field[] fields = entry.getValue().getClass().getDeclaredFields();
            for (Field field : fields) {
                if (!field.isAnnotationPresent(STAutowired.class)) {
                    continue;
                }

                STAutowired autowired = field.getAnnotation(STAutowired.class);

                // 如果用户没有自定义beanName,默认根据类型注入
                String beanName = autowired.value().trim();
                if ("".equals(beanName)) {
                    beanName = field.getType().getName();
                }
                field.setAccessible(true);
                try {
                    // 用反射机制动态赋值
                    field.set(entry.getValue(), ioc.get(beanName));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void initHandlerMapping() {
        if (ioc.isEmpty()) {
            return;
        }

        for (Map.Entry<String, Object> entry : ioc.entrySet()) {
            Class<?> clazz = entry.getValue().getClass();
            if (!clazz.isAnnotationPresent(STController.class)) {
                continue;
            }
            // 类上面的url
            String baseUrl = "";
            if (clazz.isAnnotationPresent(STRequestMapping.class)) {
                STRequestMapping mapping = clazz.getAnnotation(STRequestMapping.class);
                baseUrl = mapping.value();
            }

            // 默认获取所有的public方法
            for (Method method : clazz.getMethods()) {
                if (!method.isAnnotationPresent(STRequestMapping.class)) {
                    continue;
                }
                STRequestMapping requestMapping = method.getAnnotation(STRequestMapping.class);

                // 优化
                String url = ("/" + (baseUrl) + "/" + requestMapping.value()).replaceAll("/+", "/");

                handlerMapping.put(url, method);
                System.out.println("Mapped :" + url + "," + method);
            }
        }
    }
}

Spring实现 V3

public class STDispatchServlet extends HttpServlet {
    private static final long serialVersionUID = 823658696654581429L;

    // 保存配置文件
    private final Properties contextConfig = new Properties();

    // 保存类名
    private final List<String> classNames = new ArrayList<String>();

    // ioc容器,暂时不考虑ConcurrentHashMap
    private final Map<String, Object> ioc = new HashMap<String, Object>();

    // 保存url和method的对应关系
//    private final Map<String, Object> handlerMapping = new HashMap<String, Object>();

    // 思考为何不用map
    // 从性能上
    private List<HandlerMapping> handlerMapping = new ArrayList<HandlerMapping>();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 6.调用
        try {
            doDispatch(req, resp);
        } catch (Exception exception) {
            exception.printStackTrace();
            resp.getWriter().write("500 Exception, Detail :" + Arrays.toString(exception.getStackTrace()));
        }
        super.doPost(req, resp);
    }

    private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {


        HandlerMapping handlerMapping = getHandler(req);

        if (this.handlerMapping == null) {
            resp.getWriter().write("404 Not Found!");
            return;
        }

        // 获得方法的形参列表
        assert handlerMapping != null;
        Class<?> [] paramTypes =  handlerMapping.getParamTypes();

        Object [] paramValues = new Object[paramTypes.length];

        Map<String, String[]> params = req.getParameterMap();
        for (Map.Entry<String, String[]> param : params.entrySet()) {
            String value = Arrays.toString(param.getValue()).replaceAll("\\[|\\]]", "")
                    .replaceAll("\\s", "");
            if (handlerMapping.paramIndexMapping.containsKey(param.getKey())) {
                continue;
            }
            int index = handlerMapping.paramIndexMapping.get(param.getKey());
            paramValues[index] = convert(paramTypes[index], value);
        }

        if (handlerMapping.paramIndexMapping.containsKey(HttpServletRequest.class.getName())) {
            int reqIndex = handlerMapping.paramIndexMapping.get(HttpServletRequest.class.getName());
            paramValues[reqIndex] = req;
        }

        if (handlerMapping.paramIndexMapping.containsKey(HttpServletResponse.class.getName())) {
            int respIndex = handlerMapping.paramIndexMapping.get(HttpServletResponse.class.getName());
            paramValues[respIndex] = resp;
        }


        Object returnValue = handlerMapping.method.invoke(handlerMapping.controller, paramValues);
        if (returnValue == null) {
            return;
        }
        resp.getWriter().write(returnValue.toString());
    }

    private HandlerMapping getHandler(HttpServletRequest req) {
        if (handlerMapping.isEmpty()) {
            return null;
        }
        String url = req.getRequestURI();
        String contextPath = req.getContextPath();
        url = url.replaceAll(contextPath, "").replaceAll("/+", "/");

        for (HandlerMapping mapping : this.handlerMapping) {
            if (mapping.getUrl().equals(url)) {
                return mapping;
            }
        }
        return null;

    }

    // url传过来的参数都是String,HTTP时基于字符串的协议
    private Object convert(Class<?> type, String value) {
        if (Integer.class == type) {
            return Integer.valueOf(value);
        }
        // 如果还有double还要加if
        return value;
    }

    @Override
    public void init(ServletConfig config) throws ServletException {

        // 1.加载配置文件
        doLoadConfig(config.getInitParameter("contextConfigLocation"));

        // 2.扫描相关的类
        doScanner(contextConfig.getProperty("scanPackage"));

        // 3.初始化扫描到的类,并将他们放入到IOC容器中
        doInstance();

        // 4.完成依赖注入
        doAutowired();

        // 5.初始化handlerMapping
        initHandlerMapping();

        System.out.println("ST Spring Framework");

        super.init(config);
    }

    // 加载配置文件
    private void doLoadConfig(String contextConfigLocation) {
        InputStream fis = null;
        // 从类路径下找到spring主配置文件
        // 并且将其读取出来放到Properties对象中
        // 把scanPackage=cn.simplethinking.springframwork读到内存中
        fis = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
        try {
            contextConfig.load(fis);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != fis) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 扫描出类
    private void doScanner(String scanPackage) {
        // 包路径
        // 转为文件路径,实际上把.换成/就可以了
        URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
        File classPath = new File(url.getFile());
        for (File file: classPath.listFiles()) {
            if (file.isDirectory()) {
                doScanner(scanPackage + "." + file);
            } else {
                if (file.getName().endsWith(".class")) {
                    continue;
                }
                String className = (scanPackage + "." + file.getName().replace(".class", ""));
                classNames.add(className);
            }
        }
    }

    private void doInstance() {
        // 初始化,为DI准备
        if (classNames.isEmpty()) {return;}
        try {
            for (String className : classNames) {
                Class<?> clazz = Class.forName(className);
                // 什么样的类才要初始化
                // 加了注解的类c才需要初始化
                // 为了简化代码逻辑,只简化@Controller、@Service
                if (clazz.isAnnotationPresent(STController.class)
                        || clazz.isAnnotationPresent(STService.class)) {
                    Object instance = clazz.newInstance();
                    // key: className 首字母小写
                    // Spring 默认首字母小写
                    String beanName = toLowerFirstCase(clazz.getSimpleName());
                    ioc.put(beanName, instance);
                } else if (clazz.isAnnotationPresent(STService.class)) {
                    // 1.自定义beanName
                    STService stService = clazz.getAnnotation(STService.class);
                    String beanName = stService.value();
                    // 2.默认首字母小写
                    if ("".equals(beanName.trim())) {
                        beanName = toLowerFirstCase(clazz.getSimpleName());
                    }
                    Object instance = clazz.newInstance();
                    ioc.put(beanName, instance);
                    // 3.根据类型自动赋值
                    for (Class<?> i : clazz.getInterfaces()) {
                        if (ioc.containsKey(i.getName())) {
                            throw new Exception("The ”" +  i.getName()  + " “is exist");
                        }
                        ioc.put(i.getName(), instance);
                    }
                } else {
                    continue;
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    /**
     * 默认不存在类名首字母小写的情况
     * @param simpleName
     * @return
     */
    private String toLowerFirstCase(String simpleName) {
        char[] chars = simpleName.toCharArray();
        // 之所以加32,是因为大小写字母恶ASCII码相差32
        // 而且大写字母的ASCII码小于小写字母的ASCII码
        // 在Java中,对char作算学运算,实际上就是对ASCII码做运算
        chars[0] += 32;
        return String.valueOf(chars);
    }

    private void doAutowired() {
        if (ioc.isEmpty()) {
            return;
        }
        for (Map.Entry<String, Object> entry : ioc.entrySet()) {
            // Declared
            Field[] fields = entry.getValue().getClass().getDeclaredFields();
            for (Field field : fields) {
                if (!field.isAnnotationPresent(STAutowired.class)) {
                    continue;
                }

                STAutowired autowired = field.getAnnotation(STAutowired.class);

                // 如果用户没有自定义beanName,默认根据类型注入
                String beanName = autowired.value().trim();
                if ("".equals(beanName)) {
                    beanName = field.getType().getName();
                }
                field.setAccessible(true);
                try {
                    // 用反射机制动态赋值
                    field.set(entry.getValue(), ioc.get(beanName));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void initHandlerMapping() {
        if (ioc.isEmpty()) {
            return;
        }

        for (Map.Entry<String, Object> entry : ioc.entrySet()) {
            Class<?> clazz = entry.getValue().getClass();
            if (!clazz.isAnnotationPresent(STController.class)) {
                continue;
            }
            // 类上面的url
            String baseUrl = "";
            if (clazz.isAnnotationPresent(STRequestMapping.class)) {
                STRequestMapping mapping = clazz.getAnnotation(STRequestMapping.class);
                baseUrl = mapping.value();
            }

            // 默认获取所有的public方法
            for (Method method : clazz.getMethods()) {
                if (!method.isAnnotationPresent(STRequestMapping.class)) {
                    continue;
                }
                STRequestMapping requestMapping = method.getAnnotation(STRequestMapping.class);

                // 优化
                String url = ("/" + (baseUrl) + "/" + requestMapping.value()).replaceAll("/+", "/");
                this.handlerMapping.add(new HandlerMapping(url, entry.getValue(), method));
//                handlerMapping.put(url, method);
                System.out.println("Mapped :" + url + "," + method);
            }
        }
    }

    // 保存了一个url和一个method的关系
    public class HandlerMapping {
        private String url;
        private Method method;
        private Object controller;
        private Class<?> [] paramTypes;

        // 保存形参列表
        // 参数的名字作为key,参数的位置作为值
        private Map<String, Integer> paramIndexMapping;

        public HandlerMapping() {
        }

        public HandlerMapping(String url, Object controller, Method method) {
            this.url = url;
            this.method = method;
            this.controller = controller;
            paramTypes = method.getParameterTypes();
            paramIndexMapping = new HashMap<String, Integer>();
            putParamIndexMapping(method);
        }

        private void putParamIndexMapping(Method method) {
            // 因为一个字段可以有多个注解,而一个方法又有多个参数
            Annotation[][] pa =  method.getParameterAnnotations();
            for (int i = 0; i < pa.length; i++) {
                for(Annotation a : pa[i]) {
                    if (a instanceof STRequestParam) {
                        // 拿到参数的名称,方便去url去匹配
                        String paramName = ((STRequestParam) a).value();
                        if (!"".equals(paramName.trim())) {
                            paramIndexMapping.put(paramName, i);
                        }
                    }
                }
            }

            //获取形参列表
            Class<?>[] parameterTypes = method.getParameterTypes();
            for (int i = 0; i < parameterTypes.length; i++) {
                Class<?> type = parameterTypes[i];
                if (type == HttpServletRequest.class ||
                        type == HttpServletResponse.class) {
                    paramIndexMapping.put(type.getName(), i);
                }
            }
        }

        public String getUrl() {
            return url;
        }

        public Method getMethod() {
            return method;
        }

        public Object getController() {
            return controller;
        }

        public Map<String, Integer> getParamIndexMapping() {
            return paramIndexMapping;
        }

        public Class<?>[] getParamTypes() {
            return paramTypes;
        }
    }
}