zoukankan      html  css  js  c++  java
  • 自己实现spring核心功能 一

    聊聊spring

           spring对于java开发者来说,是最熟悉不过的框架了,我们日常开发中每天都在使用它。它有着各种各样的好处,简单易用,得心应手... ...

    我们一说到spring就会讲到ioc 、aop、依赖注入,注解等专业名词,不少刚接触java的人,都是一头雾水,很难直观的去理解这些是个什么玩意,但使用的多了 就爱上了它给我们带来的便利。

    探索spring

         当我们熟练的使用它之后就会好奇,ioc怎么实现的呢?为什么我只要在类的变量中加入@AutoWrited 就能使用这个变量?带着疑惑我们就会开始翻源码,找答案。经过一番努力,最终我们定位到了spring-context.jar包,找到了

    AbstractApplicationContext对象的refresh方法,这里面的实现和步骤,就是整个spring功能的核心,里面的实现另我们叹为观止,但也相当之复杂,用到了很大设计模式,难以窥见全貌,很多地方的设计我们不知道为啥需要这么实现。但我们还是知道了ioc容器实际上是用的Hashmap,
    依赖注入使用的是反射,aop实际上是动态代理完成的。还有很大一部分代码看的有点晕,就是加强健壮性保证生命周期和各种特性的。不管怎么说,那都是别人的东西,我们只会用,源码我们看了很多,但很少自己来实现出来。

    spring实现分析

      不管怎么说,别人的实现是别人的,自己写出来的东西是属于我们自己的。既然下决心要自己也能实现了,那我们就需要分析分析了。

          spring怎么做到代码侵入量少且各层级分明的呢?

             spring采用约定大于配置,按照固定模式,层级分为Controller 、Service、Component、Bean、Configuration来标识类型

          spring是怎么管理依赖关系的?

              是通过注解或xml

          spring是怎么发现哪些类需要管理的?

              是注解标记+包路径扫描

          spring是如何实现依赖注入的?

             通过AutoWrited注解标记加反射实例化对象

          spring是如何管理Bean的?

             使用HashMap容器、Set容器实现单例Bean

          spring怎么实现aop切面的呢?

             使用动态代理的方式,并提供了cglib和jdk默认实现两种方式

          spring是在何时加载到内存中的呢?

             springMvc是通过web.xml配置入口触发,springboot是通过springApplication初始化触发

     本次实现spring核心功能会涉及到哪些点?

          1.注解的定义与使用

          2.容器的初始化

          3.配置文件的读取与使用

          4.sevlet的使用

          5.注解的定义与使用

          6.反射的运用

          7.url路由与方法映射

          8.参数解析与绑定

          9.正则与转义

     正式开始

      首先创建一个maven项目,代码结构如下:

    添加jar包依赖:

    里面有2个jar包加一个插件

    javax.servlet-api.jar 用来启动核心代码和处理请求
    fastjson.jar          用来做json参数绑定

    jetty-maven-plugin 使用jetty作为web容器启动


    完整maven代码如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.honstat</groupId>
        <artifactId>test-spring</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>4.0.1</version>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.56</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.eclipse.jetty</groupId>
                    <artifactId>jetty-maven-plugin</artifactId>
                    <version>9.4.5.v20170502</version>
                    <configuration>
                        <scanIntervalSeconds>10</scanIntervalSeconds>
                        <webApp>
                            <contextPath>/</contextPath>
                        </webApp>
                        <httpConnector>
                            <port>8080</port>
                        </httpConnector>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    View Code

     创建前端控制器类

      前端控制器专门处理servlet请求,匹配到对应的方法执行后返回,前端控制器是什么可以参考我的另一篇博客《SpringMvc请求处理流程与源码探秘》

       这里我们创建一个叫CJDispatcherServlet的类,它继承HttpServlet类,并且重写HttpServlet的init(),doGet(),doPost() 这3个方法,图中的HomeService和StudentService可以先忽略不写

     配置web.xml

     需要配置<servlet> 和<servlet-mapping> 2个标签

    <servlet>中需要

    1.指定servlet名称

     2.指定处理请求的前端控制器类

     3.设置初始化配置文件路径

     完整web.xml文件如下:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
    
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    
             version="2.5">
        <servlet>
            <servlet-name>cjservletMVC</servlet-name>
            <servlet-class>com.honstat.spring.service.CJDispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>spring/application.properties</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>cjservletMVC</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    </web-app>
    View Code

     添加注解

     我们知道,spring里面是通过给类加注解来识别各种使用场景的,那我们就来实现几个必用的

    作用在类上的:

      JCController

      JCService

      JCComponent

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

     全部采用这种类型

    作用在方法上和类上的:

    JCRequestMapping

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

    作用在字段上的:

    JCAutoWrited

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

    到此我们已经初步的创建完了需要准备的类,准备工作告一段落。

    
    

     由于篇幅有限,下一篇开始实现核心功能了!

     完整代码地址

  • 相关阅读:
    Windows10下VirtualBox安装CentOS7网络配置:添加DNS
    Windows下LaTeX环境: SumatraPDF + notepad++/ST3
    Windows10 环境变量设置: "此环境变量太大"
    修改CMD字体后导致乱码的恢复方法
    nfs:server is not responding,still trying 原因与解决方案
    [GIT] 更新.repo目录
    linux网络栈相关
    linux mailbox模型
    虚拟机ping不通主机,主机能ping 通虚拟机问题解决
    pygame学习
  • 原文地址:https://www.cnblogs.com/jingch/p/11368982.html
Copyright © 2011-2022 走看看