手写spring代码

package mvcframework.servlet;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;

public class GPDispatcherServlet extends HttpServlet {

    private Properties contextConfig = new Properties();

    private List<String> classNmmes = new ArrayList<>();

    private Map<String,Object> ioc = new HashMap<>();

    private Map<String,Method> handlerMapping = new HashMap<>();

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //6.执行,调度
        try {
            doDispatch(req,resp);
        } catch (Exception e) {
            e.printStackTrace();
            resp.getWriter().write("500 Exception Detail : " + Arrays.toString(e.getStackTrace()));
        }
    }

    private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception{
        String uri = req.getRequestURI();
        String contextPath = req.getContextPath();
        uri = uri.replaceAll(contextPath,"").replaceAll("/+","/");

        if(!this.handlerMapping.containsKey(uri)){
            resp.getWriter().write("404 Not Found!!");
        }

        Method method = this.handlerMapping.get(uri);

        Map<String, String[]> params = req.getParameterMap();

        String beanName = toLowerFirstCase(method.getDeclaringClass().getSimpleName());

        Object bean = ioc.get(beanName);

        method.invoke(bean, new Object[]{req,resp,params.get("name")});
    }

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

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

        //2.扫描包路径,提取相关的类
        doScanner(contextConfig.getProperty("scanPackage"));

        //3.初始化ioc,并且将扫描到的所有的类实例化放入到ioc容器之中
        doInstance();

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

        //5.初始化HandlerMapper,建立URL和Controller映射
        doInitHandlerMapping();

        System.out.println("GP Spring framework is init...");
    }

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

        for (Map.Entry<String, Object> entry : ioc.entrySet()) {
            //获取所有的Public方法
            Method[] methods = entry.getValue().getClass().getMethods();
            //判断是否是controller注解
            if(!entry.getValue().getClass().isAnnotationPresent(Controller.class)){
                continue;
            }
            //类上面的requestmapping
            String baseUrl = "";
            if (entry.getValue().getClass().isAnnotationPresent(RequestMapping.class)) {
                RequestMapping requestMapping = entry.getValue().getClass().getAnnotation(RequestMapping.class);
                baseUrl = requestMapping.value()[0];
            }

            for (Method method : methods) {
                if(!method.isAnnotationPresent(RequestMapping.class)){
                    continue;
                }

                RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
                //替换多的斜杠,只保留一个斜杠
                String url = ("/" + baseUrl + "/" + requestMapping.value()[0]).replace("/+","/");
                if(handlerMapping.containsKey(url)){
                    try {
                        throw new Exception("url already exists..");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                handlerMapping.put(url,method);

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

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

        for (Map.Entry<String, Object> entry : ioc.entrySet()) {
            //得到所有对象的属性字段,获取所有的字段包含private(Declared)
            Field[] fields = entry.getValue().getClass().getDeclaredFields();
            //扫描,编码规范,尽量不要超过三层嵌套
            for (Field field : fields) {
                if(!field.isAnnotationPresent(Autowired.class)){
                    continue;
                }
                Autowired autowired = field.getAnnotation(Autowired.class);
                String beanName = autowired.toString();
                if("".equals(beanName)){
                    //获取字段的类型的名称
                    beanName = field.getType().getName();
                }
                //私有的field进行强制访问
                field.setAccessible(true);
                try {
                    //用的是反射
                    //xx = ioc.get(beanName);
                    field.set(entry.getValue(),ioc.get(beanName));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    continue;
                }


            }
        }
    }

    private void doInstance() {
        if (classNmmes.isEmpty()) {
            return;
        }

        try{
            for (String classNmme : classNmmes) {
                Class<?> clazz = Class.forName(classNmme);
                //此处的controller和service是可以自己些aop的,教程里面是老师自己写的
                if(clazz.isAnnotationPresent(Controller.class)) {
                    String beanName = toLowerFirstCase(clazz.getSimpleName());
                    Object instance = clazz.newInstance();
                    ioc.put(beanName,instance);
                }else if(clazz.isAnnotationPresent(Service.class)){

                    //1:默认是类名首字母小写
                    String beanName = toLowerFirstCase(clazz.getSimpleName());

                    //2.不同包 下类名相同,注解派上用场,自定义类名
                    Service service = clazz.getAnnotation(Service.class);
                    if("".equals(service.value())){
                        beanName = service.value() ;
                    }
                    Object instance = clazz.newInstance();
                    ioc.put(beanName, instance);

                    //3.根据接口类型,要实例化接口的实现类
                    for (Class<?> i : clazz.getInterfaces()) {
                        if(ioc.containsKey(i.getName())){
                            throw new Exception("The beanName is exists!");
                        }
                        ioc.put(i.getName(),instance);
                    }
                }else{
                    continue;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //首字母大写转换小写
    private String toLowerFirstCase(String simpleName) {
        char [] chars = simpleName.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }

    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.getName());
            }else{
                //等会儿可以使用Class.forName()方法可有找到下一层
                if(!file.getName().endsWith(".class")){
                    continue;
                }
                String className = (scanPackage + "." +  file.getName()).replace(".class", "");
                classNmmes.add(className);
            }
        }


    }

    private void doLoadConfig(String contextConfigLocation) {
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);

        try {
            contextConfig.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(null != is){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

自己记录使用

此代码未经过测试,仅仅限于思路

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值