spring的ioc,di,mvc 的简单逻辑(根据网课和百度)

为了提升自己的技术所以没事自己通过百度和找资料来学习了一下spring的思想所以就记录一下

这个是比较简单的一种,有点乱。我按照自己的理解写的有注释,但是不知道是不是都是正确,如果有错误希望批评指正谢谢。

总结:

1:首先要了解spring的整体:

主要作用就是ioc di mvc 和 aop ,所以要从这几个方面去入手。

想要指导思想就要从头开始,所以就总结了一下整个流程,如下:

一:首先要配置spring

1:配置web.xml中的DispatcherServlet

2:设定 init-param 配置扫描的路径:contextConfigLocation = classpath:application.xml (我写的是application.properties)

3:配置url-pattern :/*

4:配置Annotation :@Controller @RequestMapping @Service @Autowrited @RequestParam

二:继承HttpServlet并重写 init()方法开始初始化ioc

1:首先加载配置文件

(1):创建读取配置文件对象Properties

(2):以流的形式获取配置文件名称

(3):加载配置文件

(4):通过配置文件对象获取对应键值对键的值(获取之后是一个字符串:路径)

(5):开始通过路径扫描所有此路径下的文件

-1:先处理路径中把符号 “.”转换成“/”

-2:通过文件类对象File 在指定路径下获取所有的文件的Filed对象

-3:遍历所有对象,并通过判断是否是文件夹之后进行递归此方法已达到扫描到所有文件

然后在循环里面进行判断当文件是以.class结尾的就开始组合这个对象名称(通过全路径+对象名称 并去掉.class后缀)

-4:把这个对象全称保存到一个Hashmap集合里面(Map<Striing,Object>)

(6):遍历这个集合并开始ioc容器的真正初始化和di的注入

-1:去除所有kay,并判断是否是以全路径保存的(contains("."))

-2:获取该类class对象,并判断是哪种注解进行的修饰(分为两种Controller Requestmapping)

-3:分别把这三种对象和对象名称保存到集合里面

-4:获取集合里面所有的value值(map.values()),并遍历所有对象

--1:判断对象是否为空,是 跳过

--2:判断此class对象是否被@Controller注解修饰,是继续进行

--3:获取此class对象所有的属性

--4:遍历所有属性

--5:判断是否有DI注解@Autowrited,有继续进行

--6:获取此注解对象field.getAnnotation(Autowrited.class)

--7:判断注解是否有自定义

--8:没有自定义就按照类型名称进行DI注入

(7):重写dopost()he doGet()方法

(8):重写doDispatch()自定义方法(此方法实现了mvc的路径和方法的映射)

上个面是我个人的流程总结,下面是写的代码,通过网络课程 以及 百度搜索 写了一遍最简单的spring中的ioc和di的以及mvc的代码

/** * @Description: 第一个版本的spring手写 * @Author: com.syn.v1 * @Create: 2020/4/2 0002 10:28 *///1首先需要配置servlet的入口(web.xml:主要配置DispatcherServlet的入口和初始化的配置文件等)//2编写Annotation(@Controller @RequestMapping @Service @Autowritde @RequestParam)

    /*2在编写主类 DispatcherServlet 主要有一些几步:        1:继承 DispatcherServlet 初始化init方法:ioc主要就在这里实现        2:重写dopst和doget方法 并 完成 mvc的功能(另外编写一个方法专门实现)    */public class SYNDispatcherServlet extends HttpServlet{

    //创建容器   private Map<String,Object> mapping = 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 {        try {            doDispatch(req,resp);        } catch (Exception e) {            resp.getWriter().write("500 Exception "+ Arrays.toString(e.getStackTrace()));        }    }

    //这个方法是实现mvc的    private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception{        //获取除去host(域名或者ip)部分的路径        String url = req.getRequestURI();        //返回工程名部分,如果工程映射为/,此处返回则为空        /*request.getRequestURL() http://localhost:8080/jqueryLearn/resources/request.jsp        request.getRequestURI() /jqueryLearn/resources/request.jsp        request.getContextPath()/jqueryLearn*/        String contextPath = req.getContextPath();        //拼接路径,去掉多余的项目根路径和多余的斜杠        url=url.replace(contextPath,"").replaceAll("/+","/");        //判断map容器中是否有指定的路径        if(!this.mapping.containsKey(url)){resp.getWriter().write("404 Not Found!");return;}        //获取方法        Method method = (Method)this.mapping.get(url);        //获取所有参数        Map<String, String[]> parames = req.getParameterMap();        //初始化方法        method.invoke(this.mapping.get(method.getDeclaringClass().getName()),new Object[]{req,resp,parames.get("name")[0]});    }

    //这个方法是实现初始化ioc容器和di的注入    @Override    public void init(ServletConfig config) throws ServletException {

        InputStream is=null;

       try {        //一:加载配置文件        //1读取配置文件        //Properties 该类主要用于读取Java的配置文件        Properties configContext=new Properties();        //以流的形式获取配置文件的名称        is=this.getClass().getClassLoader().getResourceAsStream(config.getInitParameter("contextConfigLocation"));        //加载指定配置文件名称(以键值对形式)        configContext.load(is);        //获取指定键的值        String scanPackage = configContext.getProperty("scanPackage");        //扫描此路径下的所有文件并保存文件名称        doScanner(scanPackage);        //2:初始化容器IOC

        //遍历所有的mapping,通过 className 开始创建 需要初始化的 对象        for (String className:mapping.keySet()){            //先判断是否是全路径的文件名称            if(!className.contains(".")){continue;}            //通过Class.forName()方法 获取指定名称的class对象            Class<?> Clazz = Class.forName(className);            //判断该类对象是否有注解SYNController            if(Clazz.isAnnotationPresent(SYNController.class)){                //通过相对应的名称 创建对象并放入到 map 中                mapping.put(className,Clazz.newInstance());                //这个是在类上面requestMapping映射的路径,默认为空                String baseUrl="";                //判断类上面是否有RequestMaping注解                if(Clazz.isAnnotationPresent(SYNRequestMapping.class)){                    //获取此类上面的RequestMaping对象                    SYNRequestMapping RequestMaping = Clazz.getAnnotation(SYNRequestMapping.class);                    //赋值给baseUrl                    baseUrl=RequestMaping.value();                }                //获取此类多有方法                Method[] methods = Clazz.getMethods();                //遍历方法                for (Method method:methods){                    //方法上是否有SYNRequestMapping 注解,没有跳过                    if(!method.isAnnotationPresent(SYNRequestMapping.class)){continue;}                    //获取方法上的SYNRequestMapping对象                    SYNRequestMapping RequestMapping = method.getAnnotation(SYNRequestMapping.class);                    //组合mvc映射的路径,并通过replaceAll去掉多余的斜杠                   String url =(baseUrl+"/"+RequestMapping.value()).replaceAll("/+","/");                   //把映射路径放入到mapping(map)                    mapping.put(url,method);                    System.out.println("Mapped"+url+","+method);                }                //判断是否有SYNService注解            }else if(Clazz.isAnnotationPresent(SYNService.class)){                //获取此类上面的SYNService注解对象                SYNService synService = Clazz.getAnnotation(SYNService.class);                //获取注解上面的自定义的内容(可以为空)                String beanName = synService.value();                //判断如果为空则说明需要用到类型注入                if("".equals(beanName)){beanName=Clazz.getName();}                //初始化接口                Object instance = Clazz.newInstance();                //放入到map中                mapping.put(beanName,instance);                //遍历所有                for (Class<?> i:Clazz.getInterfaces()){                    mapping.put(i.getName(),instance);                }            }else {continue;}        }            //遍历所有map中的对象            for (Object object:mapping.values()){                //如果对象为空跳过                if(object==null){continue;}                //不为空获取对象                Class<?> clazz = object.getClass();                if(clazz.isAnnotationPresent(SYNController.class)){                    //获得类里面声明的所有字段                    Field[] fields = clazz.getDeclaredFields();                    //遍历这些                    for (Field field:fields){                    //判断是否被SYNAutowired注解修饰                        if(!field.isAnnotationPresent(SYNAutowired.class)){continue;}                        //获取注解对象                        SYNAutowired SYNautowired = field.getAnnotation(SYNAutowired.class);                        //获取注解上的内容                        String beanName=SYNautowired.value();                        if("".equals(beanName)){beanName=field.getType().getName();}                        field.setAccessible(true);                        //3:注入DI                        field.set(mapping.get(clazz.getName()),mapping.get(beanName));                    }                }            }       }catch (Exception e){           e.printStackTrace();       }finally {           if(is !=null){               try {                   is.close();               }catch (IOException e){                e.printStackTrace();               }           }       }        System.out.println("GP MVC Framework is init");    }

    //通过传入的路径扫描所有的文件并放入到map集合里面    private void doScanner(String scanPackage) {        //先把获取的键值对的值转换一下(把com.syn.demo  转换成 com/syn/demo),变成项目的的文件路径        URL resource = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));        //通过文件对象获取此路径下所有的文件        //resource.getFile() 返回指定目录下该文件的file对象        File classDir =new File(resource.getFile());        for (File file:classDir.listFiles()){            //判断file是否是目录            if(file.isDirectory()){                doScanner(scanPackage+"."+file.getName());            }else {                //判断文件是否是以 .class 结尾的,不是直接跳过                if(!file.getName().endsWith(".class")){continue;}                //把获取的文件对象整理成以全路径开头的文件名称(路径+去掉 .class 的组合)                String clazzName=(scanPackage+"."+file.getName().replace(".class",""));                mapping.put(clazzName,null);            }

        }    }}

web.xml里面的配置如下:(主要就是servlet,init-param,servlet-mapping)
 
<web-app>  <display-name>Archetype Created Web Application</display-name>  <servlet>    <servlet-name>synmvc</servlet-name>    <servlet-class>com.syn.v1.SYNDispatcherServlet</servlet-class>    <init-param>      <param-name>contextConfigLocation</param-name>      <param-value>application.properties</param-value>    </init-param>    <load-on-startup>1</load-on-startup>  </servlet>  <servlet-mapping>    <servlet-name>synmvc</servlet-name>    <url-pattern>/*</url-pattern>  </servlet-mapping></web-app>
至于Annoattion我就不写了,百度应该都有,有什么问题可以给我留言。

原文地址:https://www.cnblogs.com/songyinan/p/12623340.html

时间: 2024-12-23 20:18:18

spring的ioc,di,mvc 的简单逻辑(根据网课和百度)的相关文章

Spring之IOC/DI(反转控制/依赖注入)_入门Demo

软件152 刘安民 在平时的java应用开发中,我们要实现某一个功能或者说是完成某个业务逻辑时至少需要两个或以上的对象来协作完成,在没有使用Spring的时候,每个对象在需要使用他的合作对象时,自己均要使用像new object() 这样的语法来将合作对象创建出来,这个合作对象是由自己主动创建出来的,创建合作对象的主动权在自己手上,自己需要哪个合作对象,就主动去创建,创建合作对象的主动权和创建时机是由自己把控的,而这样就会使得对象间的耦合度高了,A对象需要使用合作对象B来共同完成一件事,A要使用

用大白话说Spring的IOC,DI

IOC(Inverse of  Control)控制反转 Java即生活,鄙人的感悟. ---------好比我们需要租房.现在我们房源不需要找到某个具体的房东(new fangdong() 房东对象才能租他的房 fangdong.rent()).如果我们对这个房东的房源不满意,离地铁太远了.....heh.我们还需要找下个房东new下个房东.IOC容器就像个中介,他手里有很多房源.而我们只要通过这个中介第三方,就可以选到合适的房源.中介的存在减少了你和房东之间的耦合度.中介增加了你的容错性,

理解Spring的AOP和Ioc/DI就这么简单

一.什么叫Ioc.DIIoc:Inversion of Control -- 控制反转 DI:Dependency Injection -- 依赖注入 其实这两个概念本质上是没有区别的,那我们先来看看什么叫做Ioc? 假设这么一个场景: 在A类中调用B类的方法,那么我们就称 A依赖B,B为被依赖(对象),相信这点大家能够理解. 传统做法: (1)直接在A(方法)中new出B类对象,然后调用B类方法 -- 硬编码耦合: (2)通过简单工厂获取B类对象,然后调用B类的方法 -- 摆脱了与B的耦合,却

Spring之IOC&amp;DI/装配Bean(一)

简介 今天学习Spring的第一天,无非也就是入门基础知识.主要了解IOC和DI部分,要熟练掌握哦~ Spring简介 1. Spring介绍 Spring是一个非常活跃的开源框架:它是一个基于Core来构架多层JavaEE系统的框架,它的主要目地是简化企业开发. Spring以一种非侵入式的方式来管理你的代码,Spring提倡"最少侵入",这也就意味着你可以适当的时候安装或卸载Spring 2. Spring框架的优势 ?方便解耦,简化开发 ?Spring就是一个大工厂,可以将所有对

Spring基础[IOC/DI、AOP]

一.Spring作用:管理项目中各种业务Bean(service类.Dao类.Action类),实例化类,属性赋值 二.Spring IOC(Inversion of Control )控制反转,也被称为依赖注入(Dependency Injection[DI]),是面向对象编程 中的一种设计理念,用来减轻程序代码之间的耦合度. IOC原理:侧重原理 在业务代码中不使用我们之间司空见惯的关键字new来构建一个业务实例,而是在配置文件中.通过xml节点来告知容器如何对内存中构建的对应类型的对象名称

spring的IOC和AOP详细讲解

1.解释spring的ioc? 几种注入依赖的方式?spring的优点? IOC你就认为他是一个生产和管理bean的容器就行了,原来需要在调用类中new的东西,现在都是有这个IOC容器进行产生,同时,要是产生的是单例的bean,他还可以给管理bean的生命周期! spring的IOC有三种注入方式 : 第一是根据属性注入 也叫set方法注入: 第二种是根据构造方法进行注入: 第三种是根据注解进行注入,这种方式我认为比较好,方便,要是bean多的话,使用前两种方式会使得配置文件过于臃肿. Spri

Spring 实践 -IoC

Spring 实践 Spring简单介绍 Spring是分层的JavaSE/EE Full-Stack轻量级开源框架.以IoC(Inverse of Control 控制反转)和AOP(Aspect Oriented Programming 面向切面编程)为内核, 代替EJB的臃肿/低效/脱离现实. 主页http://spring.io/ IoC与DI IOC: 即控制反转, 解决程序对象紧密耦合问题(方式: 工厂+反射+配置文件), 将程序中原来构造对象的操作,交给IoC容器, 当程序真正须要

IOC DI

IoC:Inversion of Control,控制反转DI:Dependency Injection,依赖注入 要理解上面两个概念,就必须搞清楚如下的问题: 参与者都有谁?依赖:谁依赖于谁?为什么需要依赖?注入:谁注入于谁?到底注入什么?控制反转:谁控制谁?控制什么?为什么叫反转(有反转就应该有正转了)?依赖注入和控制反转是同一概念吗? 下面就来简要地回答一下上述问题,把这些问题搞明白了,也就明白IoC/DI了.(1)参与者都有谁:一般有三方参与者,一个是某个对象:另一个是IoC/DI容器(

如何理解IoC/DI

IoC:Inversion of Control,控制反转DI:Dependency Injection,依赖注入 要理解上面两个概念,就必须搞清楚如下的问题: 参与者都有谁?依赖:谁依赖于谁?为什么需要依赖?注入:谁注入于谁?到底注入什么?控制反转:谁控制谁?控制什么?为什么叫反转(有反转就应该有正转了)?依赖注入和控制反转是同一概念吗? 下面就来简要地回答一下上述问题,把这些问题搞明白了,也就明白IoC/DI了.(1)参与者都有谁:一般有三方参与者,一个是某个对象:另一个是IoC/DI容器(