手写Spring IOC 和 SpringMVC框架

springMVC相当于spring+servlet

springBoot更多的偏向于注解

解读springMVC源码我们可以学习到:

     设计模式:

单例模式

工厂模式

适配器模式

1、springIOC容器(装的是bean),控制反转,依赖注入,底层相当于一个HashMap

当我们尝试下面动作时:

Object object = new Object();

spring将我们创造的对象放到一个容器中,存储到内存中,使用HashMap

Class<> clazz = class.forname("类的位置")

---启动成功后所有的bean都会放到HashMap中来

map.put(“key”,“object”)

IOC==大MAP

War xxx.war -->.class

@Service

public class Aservice{

}

@Controller

public class Acontroller{

@Autowired

privite Aservice aservice;

 

}

tomcat:  object.class  启动的过程中,加载ioc容器(Map对象)---把我们所有的声明注解的类全部实例化  例如new 对象,

1)Aservice aservice = new Aservice();

2)Map.put("aservice",aservice)

3)Acontroller acontroller = new Acontroller();

4)Map.put("acontroller",acontroller)

5)初始化Autowired在map中去寻找

Aservice aservice = map.get("aservice")此过程就是依赖注入

启动过程中bean的初始化

tomcat启动成功-->

调用

注解的定义:

   @Docunmented注解是不是包含在javaDOC中 

   @Retendion什么时候使用该注解  source、class、runtime

   @Target注解用于什么地方

   @Inherited

反射机制:

    1.Class<?> clazz = class.forname("类的位置")

               2.Aservice aservice =clazz.newInstance()    反射创建实例

               3.Class clazz = aservice.getClass()    根据实例拿到类

               4.Field[] fields = clazz.getDeclaredFields()  拿到类里面定义的所有属性

               5.Medthod [] medthod = clazz.getMedthods()  获取所有方法

               6.medthod.invoke(a.args[])  

               7.request.getRequestURI()  获取请求路径

 

接下来中重点来了----上代码:

一、定义注解

spring框架中的@Autowired

package supmain.annotation;

import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SupmainAutowiredanno {
    String value() default "";
}

   @Controller

package supmain.annotation;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SupmainControlleranno {
    String value() default "";
}

@RequrstMapping

package supmain.annotation;

import java.lang.annotation.*;

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SupmainRequestmappinganno {
    String value() default "";
}

@RequestParam

package supmain.annotation;

import java.lang.annotation.*;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SupmainRequestParamanno{
    String value() default "";
}

@Service

package supmain.annotation;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SupmainServiceanno {
    String value() default "";
}

dao层在这里太麻烦,就不写了,毕竟我们可以使用mybatis框架代替,那是另外的事情

直接上service层

简单定义一个service接口

package supmain.Service;

public interface SupmainService {
    String query(String name ,String pwd);
}

service的实现类

package supmain.Service.impl;

import supmain.Service.SupmainService;
import supmain.annotation.SupmainServiceanno;

@SupmainServiceanno("SupmainServiceImpl")//在tomcat启动的时候加载,map.put("SupmainServiceImpl",new SupmainServiceImpl())
public class SupmainServiceImpl implements SupmainService {
    @Override
    public String query(String name, String pwd) {
        return "name ==== "+name+"pwd===="+pwd;
    }
}

接下来是controller层

package supmain.Controller;

import supmain.Service.SupmainService;
import supmain.annotation.SupmainAutowiredanno;
import supmain.annotation.SupmainControlleranno;
import supmain.annotation.SupmainRequestParamanno;
import supmain.annotation.SupmainRequestmappinganno;

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

@SupmainControlleranno
@SupmainRequestmappinganno("/supmain")
public class SupmainController {
    @SupmainAutowiredanno("SupmainServiceImpl")   //map.get("SupmainServiceImpl")
    private SupmainService supmainService;//springMVC使用的key是supmainService
    @SupmainRequestmappinganno("/query")
    public void query(HttpServletRequest request, HttpServletResponse response,
                      @SupmainRequestParamanno("name") String name,
                      @SupmainRequestParamanno("pwd")String pwd){
        try {
            PrintWriter writer = response.getWriter();
            String str = supmainService.query(name,pwd);
            writer.write(str);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

最后上大餐来了----大家都知道SpringMVC最重要的核心部分是DispatcherServlet

话不多BB,那么现在就来献上此核心代码--------->>>

package supmain.servlet;

import supmain.Controller.SupmainController;
import supmain.annotation.*;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
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.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DispatcherServlet extends HttpServlet {
    List  classnames = new ArrayList();
    //这就是我们的IOC
    Map beans = new HashMap();
    //init保证在tomcat启动的时候扫描所有的类,要实例化的bean map  ioc
    //handerMap
    Map handerMap = new HashMap();
    public void init(ServletConfig servletConfig){
        //1.先要扫描
        basePackageScan("supmain");
        //2.实例化,创建bean
        doInstance();
        //3.注入属性
        doAutowired();
        //4.映射
        doUrlMapping();


    }
    public void doUrlMapping(){
        for (Map.Entry entry:beans.entrySet()){
            Object instance = entry.getValue();
            //反推,为了进行逻辑判断
            Class clazz = instance.getClass();
            //只有控制类才有mapping请求路径
            if (clazz.isAnnotationPresent(SupmainControlleranno.class)) {
                //获取类上mapping注解的value
                 SupmainRequestmappinganno requestmappinganno1 = clazz.getAnnotation(SupmainRequestmappinganno.class);
                 String classPath = requestmappinganno1.value();
                 Method[] methods = clazz.getMethods();
                 for (Method method : methods){
                     if (method.isAnnotationPresent(SupmainRequestmappinganno.class)){
                         SupmainRequestmappinganno requestmappinganno2 = method.getAnnotation(SupmainRequestmappinganno.class);
                         String methodPath = requestmappinganno2.value();
                         String requestPath = classPath+methodPath;
                         handerMap.put(requestPath,method);
                     }else {
                         continue;
                     }

                 }
            }else {
                continue;
            }
            }

    }
    public void doAutowired(){
        for (Map.Entry entry:beans.entrySet()){
            Object instance = entry.getValue();
            //反推,为了进行逻辑判断
            Class clazz = instance.getClass();
            if (clazz.isAnnotationPresent(SupmainControlleranno.class)){
                //得到所有的变量
                Field[] fields = clazz.getDeclaredFields();
                for (Field field :fields){
                    if (field.isAnnotationPresent(SupmainAutowiredanno.class)){
                        SupmainAutowiredanno autowiredanno = field.getAnnotation(SupmainAutowiredanno.class);
                        String key = autowiredanno.value();
                        //拿到对象实例
                        Object bean = beans.get(key);
                        //注入   先打破封装
                        field.setAccessible(true);
                        try {
                            field.set(instance,bean);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }


                    }else {
                        continue;
                    }
                }
            }else {
                continue;
            }

        }
    }

    public void doInstance(){
        for (String classname: classnames){
            //去掉后缀名class
            String cn = classname.replace(".class","");
            //System.out.println(cn+"大家打开短短两开门v");
            try {
                Class  clazz = Class.forName(cn);
                if (clazz.isAnnotationPresent(SupmainControlleranno.class)){
                    //控制类
                    //实例化对象
                    Object instance = clazz.newInstance();
                    //拿到注解对象
                    SupmainRequestmappinganno requestmappinganno = clazz.getAnnotation(SupmainRequestmappinganno.class);
                    //拿到注解中的key
                    String key = requestmappinganno.value();
                    //创建map
                    beans.put(key,instance);
                }else if (clazz.isAnnotationPresent(SupmainServiceanno.class)){
                    //服务类
                    //实例化对象
                    Object instance = clazz.newInstance();
                    //拿到注解对象
                    SupmainServiceanno serviceanno = clazz.getAnnotation(SupmainServiceanno.class);
                    //拿到注解中的key
                    String key = serviceanno.value();
                    //创建map
                    beans.put(key,instance);
                }else {
                    continue;
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
    private void basePackageScan(String basePackage){
        //扫描编译好的类路径
        URL url =  this.getClass().getClassLoader().
                getResource(basePackage.replaceAll("\\.","/"));
       // System.out.println("奶大大大大大大大大大嘎达"+url);
        String fileStr = url.getFile();
        File file = new File(fileStr);
        String [] fileStrs = file.list();
       // System.out.println(fileStr+"dadadadadada");
        for (String path:fileStrs){

            //System.out.println("你好你的路径是567------"+path);
            File filepath =new File(fileStr+File.separator+path);
            //System.out.println(filepath);
            if (filepath.isDirectory()){
                //System.out.println("你好你的路径是------"+basePackage+"."+path);
                basePackageScan(basePackage+"."+path);
            }else {
                //System.out.println("你好你的路径是123------"+basePackage+"."+path);
                classnames.add(basePackage+"."+filepath.getName());
            }
        }


    }
    @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 {
        String url = req.getRequestURI();
        //得到上下文路径
        String context = req.getContextPath();
        //将上下文路径从路径中切掉
        String path = url.replace(context,"");
        //得到该方法
        Method method  = (Method) handerMap.get(path);
        SupmainController instance = (SupmainController) beans.get("/"+path.split("/")[1]);
        Object[] args = hand(req,resp,method);

        try {
            method.invoke(instance,args);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    private static Object[] hand(HttpServletRequest request,HttpServletResponse response,Method method){
        //拿到当前执行的方法中有哪些参数
        Class[] paramClazzs = method.getParameterTypes();
//        System.out.println("paramClazzs中的数据为:"+paramClazzs.toString());
        //根据参数的个数,new 一个参数的数组,将方法里的所有参数赋值到args来
        Object[] args = new Object[paramClazzs.length];
        int args_i = 0;
        int index = 0;
        for (Class paraClazz : paramClazzs){
            System.out.println("paraClazz的数据为:"+paraClazz);
            if (ServletRequest.class.isAssignableFrom(paraClazz)){
                args[args_i++]=request;
            }
            if (ServletResponse.class.isAssignableFrom(paraClazz)){
                args[args_i++]=response;
            }
            Annotation[] paramAns = method.getParameterAnnotations()[index];
            if (paramAns.length>0){
                for (Annotation paramAn:paramAns) {
                    if (SupmainRequestParamanno.class.isAssignableFrom(paramAn.getClass())) {
                        SupmainRequestParamanno requestParamanno = (SupmainRequestParamanno) paramAn;
                        args[args_i++] = request.getParameter(requestParamanno.value());
                    }
                }
            }
            index++;
        }
return args;
    }
}

最后我的代码结构示意图是这样的,大家可以直接把代码按照我这样的结构拷贝过去,应该就可以使用了

手写Spring IOC 和 SpringMVC框架_第1张图片

 如果本文章能够帮助到大家,我很开心!嘻嘻....

你可能感兴趣的:(知识,学习)