spring学习篇之手写Spring--version1.0

前言

未读spring源码之前手写spring的初始版本

准备

1、项目依赖与配置下载地址
https://download.csdn.net/download/shen_yun2017/12686004
在这里插入图片描述

2、LZYDispatchServlet类继承HttpServlet并重写init()、doPost、doGet方法。
项目结构,注解的定义参考https://blog.csdn.net/shen_yun2017/article/details/107646256
在这里插入图片描述

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

//存储路劲
private List<String> classPath = new ArrayList<String>();

//IoC容器
private Map<String,Object> springIoC = new HashMap<String, Object>();

//路径容器
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 {
    doDispatch(req,resp);
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {

    String properties=servletConfig.getInitParameter("contextConfigLocation");
    //1、加载配置文件
    doConfig(properties);

    //2、获取classpath
    String scanPackage=contextConfig.getProperty("scanPackage");
    doClassPath(scanPackage);

    //3、创建IoC容器容器,与实例化
    createIoC();

    //4、注入
    doAutowired();


    //5、初始化HandlerMapping
    initHandlerMapping();
}
    //首字母小写
private String toLowerFirstChar(String simpleName) {
    char[] chars = simpleName.toCharArray();
    chars[0]+=32;
    System.out.println(chars.toString());

    return String.valueOf(chars);
}

一、加载spring配置文件

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();
            }
        }
    }
}

}

二、获取扫描路劲得到classpath

    private void doClassPath(String scanPackage) {
        String  resource = this.getClass().getClassLoader().getResource(scanPackage.replaceAll("\\.","/")).getPath();
//        .replaceAll("%20"," ")

        File file = new File(resource);
        for (File file1: file.listFiles()) {
            String filepath = scanPackage + "."+file1.getName();
            if(file1.isDirectory())
                doClassPath(filepath);
            if (file1.getName().endsWith(".class")){
//                resource.replaceAll(".class","");
                classPath.add(filepath.replaceAll(".class",""));
            }
        }
    }

三、IoC容器创建于通过反射创建实体

private void createIoC() {
        for (String className:classPath)
            try {
                Class<?> aClass = Class.forName(className);
                Object instance = null;
                String springIoCKey = null;
                //什么样的类需要注入,而什么类需要实例化
                if (aClass.isAnnotationPresent(LZYController.class)) {
                    instance = aClass.newInstance();
                    springIoCKey=toLowerFirstChar(aClass.getSimpleName());
                }else if (aClass.isAnnotationPresent(LZYService.class)){
                    LZYService annotation = aClass.getAnnotation(LZYService.class);
                    springIoCKey = annotation.value();
                    if("".equals(springIoCKey.trim())){
                        springIoCKey = toLowerFirstChar(aClass.getSimpleName());
                    }
                    instance = aClass.newInstance();
                    for (Class<?> interfaceClass:aClass.getInterfaces()){
                        if (springIoC.containsKey(interfaceClass.getSimpleName())){
                            throw new RuntimeException("this is "+interfaceClass.getName()+"is exit !!");
                        }
                        springIoC.put(interfaceClass.getSimpleName(),instance);
                    }
                }else continue;
                if (instance != null)
                springIoC.put(springIoCKey,instance);
//                aClass.getAnnotations();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
    }

四、DI完成依赖注入

 private void doAutowired() {
        for (Map.Entry bean: springIoC.entrySet()) {
            Object value = bean.getValue();
            Field[] declaredFields = value.getClass().getDeclaredFields();
            for (Field field: declaredFields) {
                if (!field.isAnnotationPresent(LZYAutoWired.class)){
                    continue;
                }
                String autowiredValueName = field.getDeclaredAnnotation(LZYAutoWired.class).value().trim();
                if ("".equals(autowiredValueName)){
                    autowiredValueName = field.getType().getName();
                }
                field.setAccessible(true);


                try {
                    field.set(bean.getValue(),springIoC.get(autowiredValueName));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }

            }

        }
    }

五、构建HandMapping(URL与方法之间映射对应关系)

/**
 * @Date: 2020/8/3 20:48
 * @description :
 * @author :lzy
 * @params: []
 * @return: void
 * @other: 初始化handlmapping,让url处理方法对应
*/
private void initHandlerMapping() {
    for (Map.Entry bean: springIoC.entrySet()) {
        Class<?> aClass = bean.getValue().getClass();

        Method[] methods = aClass.getMethods();

        StringBuffer url = new StringBuffer("/");

        if (aClass.isAnnotationPresent(LZYRequestMapping.class)){
            url.append(aClass.getAnnotation(LZYRequestMapping.class).value())
                .append("/");
        }

        for (Method method:methods) {
            if (method.isAnnotationPresent(LZYRequestMapping.class)){
                url.append(method.getAnnotation(LZYRequestMapping.class).value());
                handlerMapping.put(url.toString().replaceAll("/+","/"),method);
            }
        }

    }
}

六、请求的分发

private void doDispatch(HttpServletRequest req, HttpServletResponse resp) {
        String url = req.getRequestURI();
        String contextPath = req.getContextPath();
        try {
            if (!handlerMapping.containsKey(url)){
                resp.getWriter().print("404 not found");
                return;
            }
            Method method = handlerMapping.get(url);
            Map<String,String[]> params = req.getParameterMap();

            Class<?>[] parameterTypes = method.getParameterTypes();
            Object [] parameterValues=new Object[parameterTypes.length];


            for (int i=0;i<parameterTypes.length;i++) {
                Class paramterType= parameterTypes[i];
                if (paramterType == HttpServletRequest.class){
                    parameterValues[i]=req;
                }if (paramterType == HttpServletResponse.class){
                    parameterValues[i]=resp;
                }if (paramterType == String.class){
//                    Annotation annotationPresent = paramterType.getAnnotation(LZYRequestParam.class);
                    Annotation[][] parameterAnnotations = method.getParameterAnnotations();
                    for (Annotation annotation: parameterAnnotations[i]){
                        if (annotation instanceof LZYRequestParam){
                            String value = ((LZYRequestParam) annotation).value();
                            if ("".equals(value)) continue;
                            parameterValues[i]= Arrays.toString(params.get(value))
                                    .replaceAll("\\[|\\]","")
                                    .replaceAll("\\s+",",");
                        }
                    }
                }
            }
            String beanName = toLowerFirstChar(method.getDeclaringClass().getSimpleName());
            method.invoke(springIoC.get(beanName),parameterValues);
        }  catch (Exception e){
            e.printStackTrace();
        }


    }

七、演示

Controller类

import com.lzy.spring.demo.service.Service;
import com.lzy.spring.framework.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @ Author     :lzy
 * @ Date       :Created in  2020/7/28 21:32
 * @ Description:
 */
@LZYController
@LZYRequestMapping("/")
public class Controller {

    @LZYAutoWired("service")
    private Service service;

    @LZYRequestMapping("hello")
    public void hello(HttpServletRequest req, HttpServletResponse resp,@LZYRequestParam("name") String name){
        try {
            resp.getWriter().print(service.qurey(name));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

service类

package com.lzy.spring.demo.service.impl;

import com.lzy.spring.demo.service.Service;
import com.lzy.spring.framework.annotation.LZYService;

/**
 * @ Author     :lzy
 * @ Date       :Created in  2020/8/4 15:40
 * @ Description:
 */
@LZYService("service")
public class ServiceImpl implements Service {

    public String qurey(String name){
        return "hello  "+name;
    }
}

访问

http://localhost:8080/hello?name=tom

在这里插入图片描述

问题记录

端口被占用

Exception in thread "Shutdown" java.lang.NoClassDefFoundError: org/apache/jasper/runtime/JspApplicationContextImpl
	at org.apache.jasper.servlet.JspServlet.destroy(JspServlet.java:411)
	at org.mortbay.jetty.servlet.ServletHolder.destroyInstance(ServletHolder.java:318)
	at org.mortbay.jetty.servlet.ServletHolder.doStop(ServletHolder.java:289)
	at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:76)
	at org.mortbay.jetty.servlet.ServletHandler.doStop(ServletHandler.java:185)
	at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:76)
	at org.mortbay.jetty.handler.HandlerWrapper.doStop(HandlerWrapper.java:142)
	at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:76)
	at org.mortbay.jetty.handler.HandlerWrapper.doStop(HandlerWrapper.java:142)
	at org.mortbay.jetty.servlet.SessionHandler.doStop(SessionHandler.java:125)
	at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:76)
	at org.mortbay.jetty.handler.HandlerWrapper.doStop(HandlerWrapper.java:142)
	at org.mortbay.jetty.handler.ContextHandler.doStop(ContextHandler.java:592)
	at org.mortbay.jetty.webapp.WebAppContext.doStop(WebAppContext.java:537)
	at org.mortbay.jetty.plugin.Jetty6PluginWebAppContext.doStop(Jetty6PluginWebAppContext.java:123)
	at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:76)
	at org.mortbay.jetty.handler.HandlerCollection.doStop(HandlerCollection.java:169)
	at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:76)
	at org.mortbay.jetty.handler.HandlerCollection.doStop(HandlerCollection.java:169)
	at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:76)
	at org.mortbay.jetty.handler.HandlerWrapper.doStop(HandlerWrapper.java:142)
	at org.mortbay.jetty.Server.doStop(Server.java:283)
	at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:76)
	at org.mortbay.jetty.Server$ShutdownHookThread.run(Server.java:561)
Caused by: java.lang.ClassNotFoundException: org.apache.jasper.runtime.JspApplicationContextImpl
	at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:50)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:271)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:247)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:239)
	... 24 more
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值