Spring框架核心原理理解

1.Spring主要分为以下几个主要的阶段
在这里插入图片描述
2:创建一个maven web项目(省略)
在这里插入图片描述
3 :添加servlet依赖

  <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>

4.配置web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>testDispatcherServlet</servlet-name>
    <servlet-class>com.test.mvcframework.servlet.TestDispatcherServlet</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>testDispatcherServlet</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>

5.创建注解:TestController,TestAuware,TestRequestMapping,TestRequestParam,TestService

package com.test.mvcframework.annotation;

import java.lang.annotation.*;

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

package com.test.mvcframework.annotation;

import java.lang.annotation.*;

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

package com.test.mvcframework.annotation;

import java.lang.annotation.*;

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

package com.test.mvcframework.annotation;

import java.lang.annotation.*;

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

package com.test.mvcframework.annotation;

import java.lang.annotation.*;

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

6.创建service以及实现类 TestServiceI,TestServiceImpl

package com.test.demo.service;

public interface TestServiceI {

    public String get(String name);
}

package com.test.demo.service.impl;


import com.test.demo.service.TestServiceI;
import com.test.mvcframework.annotation.TestService;

@TestService
public class TestServiceImpl implements TestServiceI {
    @Override
    public String get(String name) {
        return "myName is:"+name;
    }
}

7.创建Action : TestAction

package com.test.demo.mvc.action;

import com.test.demo.service.TestServiceI;
import com.test.mvcframework.annotation.TestAuware;
import com.test.mvcframework.annotation.TestController;
import com.test.mvcframework.annotation.TestRequestMapping;
import com.test.mvcframework.annotation.TestRequestParam;

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

@TestController
@TestRequestMapping("/demo")
public class TestAction {

    @TestAuware
    private TestServiceI testService;

    @TestRequestMapping("/query.json")
    public void query(HttpServletRequest request, HttpServletResponse response, @TestRequestParam String name){
        String s = testService.get(name);
        try {
            response.getWriter().write(s);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

8.编写核心代码:TestDispatcherServlet

package com.test.mvcframework.servlet;


import com.test.mvcframework.annotation.TestAuware;
import com.test.mvcframework.annotation.TestController;
import com.test.mvcframework.annotation.TestRequestMapping;
import com.test.mvcframework.annotation.TestService;

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 TestDispatcherServlet extends HttpServlet {

    private Properties contextconfig = new Properties();

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

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

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

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            doDispatch(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void doDispatch(HttpServletRequest req, HttpServletResponse resp)throws Exception {
        if(handlerMapping.isEmpty()){return;}
        String url = req.getRequestURI();
        String contextPath = req.getContextPath();
        url = url.replace(contextPath, "");
        if(!handlerMapping.containsKey(url)){
            resp.getWriter().write("404 Not Found");
            return;
        }
        Method method = handlerMapping.get(url);
        System.out.print("执行的方法名称是:"+method.getName());
        //todo 最后有待完善的是doDispatch方法的invoke方法的执行
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        //1.加载配置文件
        doLoadConfig(config.getInitParameter("contextConfigLocation"));
        //2.扫描所有相关联的类
        doScanner(contextconfig.getProperty("scanPackage"));
        //3.初始化所有相关联的类,并且将其保存到IOC容器中
        doInstance();
        //4.实现自动化依赖注入DI
        doAutoware();
        //5.初始化HandlerMapping
        initHandlerMapping();
    }

    private void initHandlerMapping() {
        if(ioc.isEmpty()){return;}
        for(Map.Entry<String,Object> entry :ioc.entrySet()){
            Class<?> clazz = entry.getValue().getClass();
            if(!clazz.isAnnotationPresent(TestController.class)){continue;}
            String baseUrl = "";
            if(clazz.isAnnotationPresent(TestRequestMapping.class)){
                TestRequestMapping testRequestMapping = clazz.getAnnotation(TestRequestMapping.class);
                baseUrl = testRequestMapping.value();
            }

            for(Method method :clazz.getMethods()){
                if(!method.isAnnotationPresent(TestRequestMapping.class)){
                    return;
                }
                TestRequestMapping testRequestMapping = method.getAnnotation(TestRequestMapping.class);
                String url = baseUrl+testRequestMapping.value();
                handlerMapping.put(url,method);
            }

        }
    }

    private void doAutoware() {
        if(ioc.isEmpty()){return;}
        for(Map.Entry<String,Object> entry :ioc.entrySet()){
            Field[] fields = entry.getValue().getClass().getDeclaredFields();
            for(Field field :fields){
                //不是所有的属性都要赋值
                if(!field.isAnnotationPresent(TestAuware.class)){
                    return;
                }
                TestAuware testAuware = field.getAnnotation(TestAuware.class);
                String beanName = testAuware.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 doInstance() {
        if(classNames.isEmpty()){
            return;
        }
        for (String className :classNames){
            try {
                Class<?> clazz = Class.forName(className);

                if(clazz.isAnnotationPresent(TestController.class)){
                    String beanName = lowerFirstCase(clazz.getSimpleName());
                   ioc.put(beanName,clazz.newInstance());
                }else if(clazz.isAnnotationPresent(TestService.class)){
                    //key的规则 1.默认类名搜字母小写 2.自定义类名  3.以实现类的实例作为值保存下来
                    TestService service = clazz.getAnnotation(TestService.class);
                    String beanName = service.value();
                    if("".equals(beanName.trim())){
                        beanName = lowerFirstCase(clazz.getSimpleName());
                    }
                    Object instance = clazz.newInstance();
                    ioc.put(beanName,instance);

                    //接口实现类的实例
                    Class<?>[] interfaces = clazz.getInterfaces();
                    for(Class<?> i :interfaces){
                        ioc.put(i.getName(),instance);
                    }
                }else {
                    //没有加注解的类都不需要初始化
                    continue;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void doScanner(String scanPackage) {
        URL url = this.getClass().getClassLoader().getResource("/"+scanPackage.replaceAll("\\.","/"));
        File classDir = new File(url.getFile());//com.test.demo下面的所有
        for(File file :classDir.listFiles()){
            if(file.isDirectory()){//如果是个文件夹就递归读下去
                doScanner(scanPackage+"."+file.getName());
            }else {
                String className = (scanPackage +"."+file.getName().replace(".class",""));
                classNames.add(className);
            }
        }
    }

    private void doLoadConfig(String contextConfigLocation) {
        InputStream inputStream =  this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
        try {
            contextconfig.load(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(null != inputStream){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    private String lowerFirstCase(String str){
        char[] chars = str.toCharArray();
        chars[0] += 32; //大小写字母之间相差32个ASCII码值
        return String.valueOf(chars);
    }
}

9.最后项目验证:http://localhost:8080/demo/query.json
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值