用30个类高仿真提炼纯手写Spring框架

项目环境搭建

application.properties 配置

为了简化XML解析, 用application.properties 来代替application.xml,具体配置如下:

#scan config
scanPackage=com.hezhiqin.demo

templateRoot=layouts


#多切面配置可以在key前面加前缀
#例如 aspect.logAspect.
#切面表达式,expression#
pointCut=public .* com.hezhiqin.demo.service..*Service..*(.*)
#切面类#
aspectClass=com.hezhiqin.demo.aspect.LogAspect
#切面前置通知#
aspectBefore=before
#切面后置通知#
aspectAfter=after
#切面异常通知#
aspectAfterThrow=afterThrowing
#切面异常类型#
aspectAfterThrowingName=java.lang.Exception

标题pom.xml 配置

<?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">
    <parent>
        <artifactId>HomeWork</artifactId>
        <groupId>hezhiqin.com</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>Spring2.1</artifactId>
    <packaging>war</packaging>

    <name>Spring2.1 Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>Spring2.1</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

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>


    <display-name>HZQmvc</display-name>
    <servlet>
      <servlet-name>hzqmvc</servlet-name>
      <servlet-class>com.hezhiqin.formework.webmvc.servlet.HZQDispathcherServlet</servlet-class>
      <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:config.properties</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
      <servlet-name>hzqmvc</servlet-name>
      <url-pattern>/*
    


IOC 顶层结构设计

annotation(自定义配置)模块
Annotation 的代码实现我们还是沿用mini 版本的不变,复制过来便可。

HZQAutowired

package com.hezhiqin.formework.annotation;

import java.lang.annotation.*;

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

HZQController

package com.hezhiqin.formework.annotation;

import java.lang.annotation.*;

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

HZQRequestMapping

package com.hezhiqin.formework.annotation;

import java.lang.annotation.*;

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

HZQRequestParam

package com.hezhiqin.formework.annotation;

import java.lang.annotation.*;

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

HZQService

package com.hezhiqin.formework.annotation;

import java.lang.annotation.*;

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

core(顶层接口)模块

HZQBeanFactory

package com.hezhiqin.formework.beans;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-10-27 13:01
 */
public interface HZQBeanFactory {
        
    /**
    *@Description: 
    *@Param: 
    *@return: 
    *@Author: hezhiqin
    *@date: 2019/10/27
    */
    Object getBean(String beanName) throws Exception;
}

beans(配置封装)模块

package com.hezhiqin.formework.beans.config;

import lombok.Data;
/**
 * @program: homeWork
 * @description:用来存储配置文件中的信息,相当于保存在内存中的配置
 * @author: hezhiqin
 * @create: 2019-10-27 13:28
 */
@Data
public class HZQBeanDefinition {
    private  String beanClassName;
    //是否延时加载
    private  boolean lazyInit = false;

    private String factoryBeanName;
    //是否单例
    private  boolean isSingleton = true;
}

GPBeanWrapper

package com.hezhiqin.formework.beans;

/**
 * @program: homeWork
 * @description: 存储Bean所有的信息(代理,依赖关系等)
 * @author: hezhiqin
 * @create: 2019-10-28 13:59
 */
public class HZQBeanWrapper {


    private  Object wrappedInstance;


    private  Class<?> wrappedClass;

    public HZQBeanWrapper(Object wrappedInstance) {
        this.wrappedInstance = wrappedInstance;
        wrappedClass = wrappedInstance.getClass();
    }

    public Object getWrappedInstance() {
        return wrappedInstance;
    }

    // 返回代理以后的Class
    // 可能会是这个$Proxy0
    public Class<?> getWrappedClass() {
        return wrappedClass;
    }


}

context(IOC 容器)模块

HZQAbstractApplicationContext

package com.hezhiqin.formework.context.support;

/**
 * @program: homeWork
 * @description: 单例工厂的顶层设计
 * @author: hezhiqin
 * @create: 2019-10-27 13:10
 */
public  abstract  class HZQAbstractApplicationContext {

    //受保护的,只提供给子类去重写
    protected void  refresh() throws ClassNotFoundException {

    }
}

HZQAbstractApplicationContext

package com.hezhiqin.formework.beans.support;

import com.hezhiqin.formework.beans.config.HZQBeanDefinition;
import com.hezhiqin.formework.context.support.HZQAbstractApplicationContext;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: homeWork
 * @description:存储注册信息的BeanDefinition
 * @author: hezhiqin
 * @create: 2019-10-27 13:16
 */
public class HZQDefaultListableBeanFactory extends HZQAbstractApplicationContext {


    /** Map of bean definition objects, keyed by bean name. */
    protected final Map<String, HZQBeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, HZQBeanDefinition>(256);



}

HZQApplicationcontext

先来看一下HZQApplicationcontext的类图,会清晰一点

用30个类高仿真提炼纯手写Spring框架_第1张图片

package com.hezhiqin.formework.context;

import com.hezhiqin.formework.annotation.HZQAutowired;
import com.hezhiqin.formework.annotation.HZQController;
import com.hezhiqin.formework.annotation.HZQService;
import com.hezhiqin.formework.aop.HZQAopProxy;
import com.hezhiqin.formework.aop.HZQCglibAopProxy;
import com.hezhiqin.formework.aop.HZQJdkDynamicAopProxy;
import com.hezhiqin.formework.aop.config.HZQAopConfig;
import com.hezhiqin.formework.aop.support.HZQAdvisedSupport;
import com.hezhiqin.formework.beans.HZQBeanFactory;
import com.hezhiqin.formework.beans.HZQBeanWrapper;
import com.hezhiqin.formework.beans.config.HZQBeanDefinition;
import com.hezhiqin.formework.beans.config.HZQBeanPostProcessor;
import com.hezhiqin.formework.beans.support.HZQBeanDefinitionReader;
import com.hezhiqin.formework.beans.support.HZQDefaultListableBeanFactory;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: homeWork
 * @description:顶级容器实现类
 * @author: hezhiqin
 * @create: 2019-10-27 13:07
 */
public class HZQApplicationcontext extends HZQDefaultListableBeanFactory implements HZQBeanFactory {

    private String[] configLocations;

    //单例的的IOC容器
    private  Map<String,Object> singletonObject= new ConcurrentHashMap<String,Object>();

    //通用的IOC容器
    private  Map<String,HZQBeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<String,HZQBeanWrapper>();

    HZQBeanDefinitionReader hzqBeanDefinitionReader;


    public HZQApplicationcontext(String... configLocations) {

        this.configLocations =configLocations;

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

    }


     public  String[] getBeanDefinitionNames(){
         Set<String> set = beanDefinitionMap.keySet();
         return  set.toArray(new String[this.beanDefinitionMap.size()]);
     }

    int getBeanDefinitionCount(){
        return  beanDefinitionMap.size();
    }

    //初始化
    @Override
    protected void refresh() throws ClassNotFoundException {
        //1.ioc第一步,定位配置文件
        hzqBeanDefinitionReader = new HZQBeanDefinitionReader(configLocations);


        //2.加载配置文件,扫描相关的类,封装成BeanDefinition
        List<HZQBeanDefinition> hzqBeanDefinitions =  hzqBeanDefinitionReader.loadBeanDefinitions();

        //3.注册,配置信息放入容器中(伪IOC容器,只保存了配置信息,真正的IOC在beanWapper)
        doRegisterBeanDefinition(hzqBeanDefinitions);

        //4.把不是延时加载的类,提前的初始化
        doAutoWrited();
    }

    private void doRegisterBeanDefinition(List<HZQBeanDefinition> hzqBeanDefinitions) {

        for (HZQBeanDefinition  hzqBeanDefinition: hzqBeanDefinitions) {
            super.beanDefinitionMap.put(hzqBeanDefinition.getFactoryBeanName(),hzqBeanDefinition);
        }


    }

    private void doAutoWrited() {
        for (Map.Entry<String,HZQBeanDefinition>  beanDefinitionEntry: super.beanDefinitionMap.entrySet()) {
            String beanName = beanDefinitionEntry.getKey();

            if (!beanDefinitionEntry.getValue().isLazyInit()){
                try {
                    getBean(beanName);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }

    }



    @Override
    public Object getBean(String beanName) throws Exception {



        HZQBeanPostProcessor hzqBeanPostProcessor = new HZQBeanPostProcessor();


        //1.初始化
        Object instantiateBean = instantiateBean(beanName,this.beanDefinitionMap.get(beanName));


        //对象封装到BeanWrapper中
        HZQBeanWrapper hzqBeanWrapper = new HZQBeanWrapper(instantiateBean);




        hzqBeanPostProcessor.postProcessBeforeInitialization(instantiateBean,beanName);




        //2.将BeanWrapper 保存的IOC 容器中
        if (!factoryBeanInstanceCache.containsKey(beanName)){
            factoryBeanInstanceCache.put(beanName,hzqBeanWrapper);
        }


        hzqBeanPostProcessor.postProcessAfterInitialization(instantiateBean,beanName);

        //3.注入
        populateBean(beanName,this.beanDefinitionMap.get(beanName),hzqBeanWrapper);


        return factoryBeanInstanceCache.get(beanName).getWrappedInstance();

    }


    //注入
    private void populateBean(String beanName, HZQBeanDefinition hzqBeanDefinition, HZQBeanWrapper hzqBeanWrapper) {
        //1、拿到实例
        Object object = hzqBeanWrapper.getWrappedInstance();

        //2.判断只有加了注解的类,才执行注入
        Class aClass = hzqBeanWrapper.getWrappedClass();

        //如果不是
        if (!(aClass.isAnnotationPresent(HZQController.class)||aClass.isAnnotationPresent(HZQService.class))){
            return;
        }

        Field[] fields = aClass.getDeclaredFields();

        for (Field field: fields) {
            if (!field.isAnnotationPresent(HZQAutowired.class)){continue;}
            //判断这个字段有没有Auto
            HZQAutowired hzqAutowired =  field.getAnnotation(HZQAutowired.class);

            String autowiredBeanName =  hzqAutowired.value().trim();

            if ("".equals(autowiredBeanName)){
                autowiredBeanName = field.getType().getSimpleName();
            }

            field.setAccessible(true);
            try {
                //为什么会为null?因为循环顺序的问题
                if (this.factoryBeanInstanceCache.get(autowiredBeanName)==null){
                    try {
                        field.set(object,Class.forName(this.beanDefinitionMap.get(autowiredBeanName).getBeanClassName()).newInstance());
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }else {
                    field.set(object,this.factoryBeanInstanceCache.get(autowiredBeanName).getWrappedInstance());
                }


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

    private Object instantiateBean(String beanName, HZQBeanDefinition hzqBeanDefinition) {

        //1.拿到要实例化的对象的类名
        String className =  hzqBeanDefinition.getBeanClassName();



        //2.反射实例化,得到对象
        Object instance = null;

        try {
            //假设默认单例
            if (singletonObject.containsKey(className)){
                instance = this.singletonObject.get(className);
            }else {
                Class<?>  aClass = Class.forName(className);
                instance = aClass.newInstance();

                HZQAdvisedSupport config = instantionAopConfig(hzqBeanDefinition);
                config.setTargetClass(aClass);
                config.setTarget(instance);

                //符合PointCut的规则的话,创建代理对象
                if(config.pointCutMatch()) {
                    instance = createProxy(config).getProxy();
                }

                this.singletonObject.put(className,instance);
                this.singletonObject.put(hzqBeanDefinition.getFactoryBeanName(),instance);
            }

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

        return  instance;
    }

    private HZQAopProxy createProxy(HZQAdvisedSupport config) {
        Class targetClass  = config.getTargetClass();
        if (targetClass.getInterfaces().length>0){
            return new HZQJdkDynamicAopProxy(config);
        }
        return new HZQCglibAopProxy(config);
    }

    private HZQAdvisedSupport instantionAopConfig(HZQBeanDefinition hzqBeanDefinition) {

        HZQAopConfig hzqAopConfig = new HZQAopConfig();
        hzqAopConfig.setPointCut(this.hzqBeanDefinitionReader.getConfigContext().getProperty("pointCut"));
        hzqAopConfig.setAspectClass(this.hzqBeanDefinitionReader.getConfigContext().getProperty("aspectClass"));
        hzqAopConfig.setAspectBefore(this.hzqBeanDefinitionReader.getConfigContext().getProperty("aspectBefore"));
        hzqAopConfig.setAspectAfter(this.hzqBeanDefinitionReader.getConfigContext().getProperty("aspectAfter"));
        hzqAopConfig.setAspectAfterThrow(this.hzqBeanDefinitionReader.getConfigContext().getProperty("aspectAfterThrow"));
        hzqAopConfig.setAspectAfterThrowingName(this.hzqBeanDefinitionReader.getConfigContext().getProperty("aspectAfterThrowingName"));
        return new HZQAdvisedSupport(hzqAopConfig);

    }

    public Properties getCongif(){
        return this.hzqBeanDefinitionReader.getConfigContext();
    }
}

HZQApplicationContextAware

package com.hezhiqin.formework.context;

/**
 * @program: homeWork
 * @description: 通过解耦的方式获取IOC容器的顶层设计
 * 后面将通过一个监听器去扫描所以的类,只要实现了此接口
 * 将自动调用setApplicationContext,从而将IOC容器注入到目标类中
 * @author: hezhiqin
 * @create: 2019-10-27 13:38
 */
public interface HZQApplicationContextAware {

    void setApplicationContext(HZQApplicationcontext  applicationContext) throws Exception;
}

完成IOC容器功能

1、寻找入口,阅读Spring的源码可以得知,入口在构造方法中,我们仿造Spring手写

	public HZQApplicationcontext(String... configLocations) {

        this.configLocations =configLocations;

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

    }

2、初始化

 	//初始化
    @Override
    protected void refresh() throws ClassNotFoundException {
        //1.ioc第一步,定位配置文件
        hzqBeanDefinitionReader = new HZQBeanDefinitionReader(configLocations);


        //2.加载配置文件,扫描相关的类,封装成BeanDefinition
        List<HZQBeanDefinition> hzqBeanDefinitions =  hzqBeanDefinitionReader.loadBeanDefinitions();

        //3.注册,配置信息放入容器中(伪IOC容器,只保存了配置信息,真正的IOC在beanWapper)
        doRegisterBeanDefinition(hzqBeanDefinitions);

        //4.把不是延时加载的类,提前的初始化
        doAutoWrited();
    }

通过HZQBeanDefinitionReader。读取配置文件,扫描指定包下的所有相关类
然后加载配置文件,扫描相关的类,封装成BeanDefinition

HZQBeanDefinitionReader

package com.hezhiqin.formework.beans.support;

import com.hezhiqin.formework.beans.config.HZQBeanDefinition;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-10-28 12:40
 */
public class HZQBeanDefinitionReader {


    //保存扫描的所有的类名
    private List<String> registyBeanClasses = new ArrayList<String>();

    //获取配置信息,定位到需要扫描的包下面
    Properties configContext = new Properties();


    private  final String  SCAN_PACKGE = "scanPackage";



    public HZQBeanDefinitionReader (String... locations){
        InputStream  is = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:",""));
        try {
            configContext.load(is);
            doScanner(configContext.getProperty(SCAN_PACKGE));
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }



    //把配置文件中扫描到的所有的配置信息转换为GPBeanDefinition对象,以便于之后IOC操作方便
    public List<HZQBeanDefinition> loadBeanDefinitions() throws ClassNotFoundException {


        List<HZQBeanDefinition>  result = new ArrayList<HZQBeanDefinition>();

        for (String  registyBeanClass: registyBeanClasses) {

            Class<?> beanClass = Class.forName(registyBeanClass);
            //如果是一个接口,是不能实例化的
            //用它实现类来实例化
            if(beanClass.isInterface()) { continue; }


            //beanName有三种情况:
            //1、默认是类名首字母小写
            //2、自定义名字
            //3、接口注入
            result.add(doCreateBeanDefintion(toLowerFirstCase(beanClass.getSimpleName()),beanClass.getName()));
//                result.add(doCreateBeanDefinition(beanClass.getName(),beanClass.getName()));

            Class<?> [] interfaces = beanClass.getInterfaces();
            for (Class<?> i : interfaces) {
                //如果是多个实现类,只能覆盖
                //为什么?因为Spring没那么智能,就是这么傻
                //这个时候,可以自定义名字
                result.add(doCreateBeanDefintion(i.getSimpleName(),beanClass.getName()));
            }


        }



        return result;
    }


    public Properties getConfigContext() {
        return configContext;
    }





    /**
     * @param scanPackage
     * 扫描配置的路径,将所有相关的类放入容器中
     */
    private void doScanner(String scanPackage) {

        //scanPackage = com.hezhiqin ,存储的是包路径
        //转换为文件路径,实际上就是把.替换为/就 OK 了
        URL url = this.getClass().getClassLoader().getResource("/" +
                scanPackage.replaceAll("\\.","/"));//将扫描的包的.换成/
        File classDir = new File(url.getFile());
        for (File file : classDir.listFiles()) {
            if (file.isDirectory()) {//如果是一个文件
                doScanner(scanPackage + "." +file.getName());
            }else {
                if(!file.getName().endsWith(".class")){continue;}//不是一个class文件则跳过
                String clazzName = (scanPackage + "." + file.getName().replace(".class",""));//获取classpath
                //
                registyBeanClasses.add(clazzName);

            }
        }


    }



    //吧每一个配置信息解析成为BeanDefintion
    private  HZQBeanDefinition doCreateBeanDefintion(String factoryBeanName,String beanClassName){
        HZQBeanDefinition hzqBeanDefinition = new HZQBeanDefinition();
        hzqBeanDefinition.setBeanClassName(beanClassName);
        hzqBeanDefinition.setFactoryBeanName(factoryBeanName);
        return  hzqBeanDefinition;
    }



    private String toLowerFirstCase(String simpleName) {
        char [] chars = simpleName.toCharArray();
        //之所以加,是因为大小写字母的 ASCII 码相差 32,
        // 而且大写字母的 ASCII 码要小于小写字母的 ASCII 码
        //在 Java 中,对 char 做算学运算,实际上就是对 ASCII 码做算学运算
        if (isUpperCase(chars[0])) {
            chars[0] += 32;
        }
        return String.valueOf(chars);

    }


    /*
     * 是否是大写
     */
    public boolean isUpperCase(char c) {
        return c >=65 && c <= 90;
    }
}

至此 我们将所有的在配置文件中"scanPackage" 下所有的类都扫描到了IOC容器中

完成DI 依赖注入功能

上面介绍的是把指定的类保存在IOC容器中,在之前的源码分析中,我们已经了解到,依赖注入的入口是从getBean()方法开始的,前
面的IOC 手写部分基本流程已通。先在HZQApplicationContext 中定义好IOC 容器,一个是HZQBeanWrapper,一个是单例对象缓存

public class HZQApplicationcontext extends HZQDefaultListableBeanFactory implements HZQBeanFactory {

    private String[] configLocations;

    //单例的的IOC容器
    private  Map<String,Object> singletonObject= new ConcurrentHashMap<String,Object>();

    //通用的IOC容器
    private  Map<String,HZQBeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<String,HZQBeanWrapper>();

}

上一步注入的方法是doAutoWrited(),我们往里走。。。。。。。

	
		private void doAutoWrited() {
        for (Map.Entry<String,HZQBeanDefinition>  beanDefinitionEntry: super.beanDefinitionMap.entrySet()) {
            String beanName = beanDefinitionEntry.getKey();

            if (!beanDefinitionEntry.getValue().isLazyInit()){
                try {
                    getBean(beanName);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }

    }

下面,我们从完善getBean()方法开始:

 @Override
    public Object getBean(String beanName) throws Exception {



        HZQBeanPostProcessor hzqBeanPostProcessor = new HZQBeanPostProcessor();


        //1.初始化
        Object instantiateBean = instantiateBean(beanName,this.beanDefinitionMap.get(beanName));


        //对象封装到BeanWrapper中
        HZQBeanWrapper hzqBeanWrapper = new HZQBeanWrapper(instantiateBean);




        hzqBeanPostProcessor.postProcessBeforeInitialization(instantiateBean,beanName);




        //2.将BeanWrapper 保存的IOC 容器中
        if (!factoryBeanInstanceCache.containsKey(beanName)){
            factoryBeanInstanceCache.put(beanName,hzqBeanWrapper);
        }


        hzqBeanPostProcessor.postProcessAfterInitialization(instantiateBean,beanName);

        //3.注入
        populateBean(beanName,this.beanDefinitionMap.get(beanName),hzqBeanWrapper);


        return factoryBeanInstanceCache.get(beanName).getWrappedInstance();

    }





	 private Object instantiateBean(String beanName, HZQBeanDefinition hzqBeanDefinition) {

        //1.拿到要实例化的对象的类名
        String className =  hzqBeanDefinition.getBeanClassName();



        //2.反射实例化,得到对象
        Object instance = null;

        try {
            //假设默认单例
            if (singletonObject.containsKey(className)){
                instance = this.singletonObject.get(className);
            }else {
                Class<?>  aClass = Class.forName(className);
                instance = aClass.newInstance();

                HZQAdvisedSupport config = instantionAopConfig(hzqBeanDefinition);
                config.setTargetClass(aClass);
                config.setTarget(instance);

                //符合PointCut的规则的话,创建代理对象
                if(config.pointCutMatch()) {
                    instance = createProxy(config).getProxy();
                }

                this.singletonObject.put(className,instance);
                this.singletonObject.put(hzqBeanDefinition.getFactoryBeanName(),instance);
            }

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

        return  instance;
    }


	//注入
    private void populateBean(String beanName, HZQBeanDefinition hzqBeanDefinition, HZQBeanWrapper hzqBeanWrapper) {
        //1、拿到实例
        Object object = hzqBeanWrapper.getWrappedInstance();

        //2.判断只有加了注解的类,才执行注入
        Class aClass = hzqBeanWrapper.getWrappedClass();

        //如果不是
        if (!(aClass.isAnnotationPresent(HZQController.class)||aClass.isAnnotationPresent(HZQService.class))){
            return;
        }

        Field[] fields = aClass.getDeclaredFields();

        for (Field field: fields) {
            if (!field.isAnnotationPresent(HZQAutowired.class)){continue;}
            //判断这个字段有没有Auto
            HZQAutowired hzqAutowired =  field.getAnnotation(HZQAutowired.class);

            String autowiredBeanName =  hzqAutowired.value().trim();

            if ("".equals(autowiredBeanName)){
                autowiredBeanName = field.getType().getSimpleName();
            }

            field.setAccessible(true);
            try {
                //为什么会为null?因为循环顺序的问题
                if (this.factoryBeanInstanceCache.get(autowiredBeanName)==null){
                    try {
                        field.set(object,Class.forName(this.beanDefinitionMap.get(autowiredBeanName).getBeanClassName()).newInstance());
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }else {
                    field.set(object,this.factoryBeanInstanceCache.get(autowiredBeanName).getWrappedInstance());
                }


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

HZQBeanWrapper

package com.hezhiqin.formework.beans;

/**
 * @program: homeWork
 * @description: 存储Bean实例的信息
 * @author: hezhiqin
 * @create: 2019-10-28 13:59
 */
public class HZQBeanWrapper {


    private  Object wrappedInstance;


    private  Class<?> wrappedClass;

    public HZQBeanWrapper(Object wrappedInstance) {
        this.wrappedInstance = wrappedInstance;
        wrappedClass = wrappedInstance.getClass();
    }

    public Object getWrappedInstance() {
        return wrappedInstance;
    }

    // 返回代理以后的Class
    // 可能会是这个$Proxy0
    public Class<?> getWrappedClass() {
        return wrappedClass;
    }


}

HZQBeanPostProcessor

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-10-31 13:49
 */
public class HZQBeanPostProcessor {


    //为在Bean 的初始化前提供回调入口
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception {
        return bean;
    }

    //为在Bean 的初始化之后提供回调入口
    public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {
        return bean;
    }
}

至此,DI 部分就完成了。
在此总结一下执行顺序:
1.refresh方法中的doAutoWrited是DI的起始点用30个类高仿真提炼纯手写Spring框架_第2张图片
2.在doAutoWrited方法中调用了getBean方法
用30个类高仿真提炼纯手写Spring框架_第3张图片
3.调用以下方法进行初始化和赋值(注入)用30个类高仿真提炼纯手写Spring框架_第4张图片

MVC 顶层设计

HZQDispatcherServlet

1.init方法中 初始化application容器,初始化九大组件

2.initHandlerMappings中将url和类,方法的关系保存起来

3.initHandlerAdapters 初始化参数适配器

  1. initViewResolvers 初始化视图转换器
package com.hezhiqin.formework.webmvc.servlet;


import com.hezhiqin.formework.annotation.HZQController;
import com.hezhiqin.formework.annotation.HZQRequestMapping;
import com.hezhiqin.formework.context.HZQApplicationcontext;
import lombok.extern.slf4j.Slf4j;

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.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Administrator
 *所有的核心逻辑卸载init方法中
 */
@Slf4j
public class HZQDispathcherServlet extends HttpServlet {

    private final String CONTEXT_CONFIG_LOCATION = "contextConfigLocation";

    private HZQApplicationcontext hzqApplicationcontext;

    private List<HZQHandlerMapping> handlerMappings  = new ArrayList<HZQHandlerMapping>();

    private Map<HZQHandlerMapping, HZQHandlerAdapter> handlerAdapters = new HashMap<HZQHandlerMapping,HZQHandlerAdapter>();


    private List<HZQViewResolver> viewResolvers = new ArrayList<HZQViewResolver>();


    @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 {
            this.doDispather(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
            resp.getWriter().write("500 Exception,Details: " + Arrays.toString(e.getStackTrace()));
        }
    }


    @Override
    public void init(ServletConfig config) throws ServletException {
       //1.初始化application
        hzqApplicationcontext = new HZQApplicationcontext(config.getInitParameter(CONTEXT_CONFIG_LOCATION));
        //2.初始化九大组件
        this.initStrategies(hzqApplicationcontext);
    }

    private void doDispather(HttpServletRequest req, HttpServletResponse resp)throws Exception {

        //1.通过重request中拿到url,去匹配一个handlerMapping
        HZQHandlerMapping handlerMapping = getHandler(req);

        if (handlerMapping==null){
            processDispatchResult(req,resp,new HZQModelAndView("404"));
            return;
        }


        //2. 准备调用钱参数
        HZQHandlerAdapter  hzqHandlerAdapter = getHandlerAdapter(handlerMapping);


        //3.真正的调用方法,返回的HZQModelAndView 包含了页面上的值,和页面模板名称
        HZQModelAndView hzqModelAndView =  hzqHandlerAdapter.handle(req,resp,handlerMapping);

        //4.真正的输出
        processDispatchResult(req,resp,hzqModelAndView);
    }

    //把给我的ModelAndView转变成HTML或者Json、freemark
    private void processDispatchResult(HttpServletRequest req, HttpServletResponse resp, HZQModelAndView hzqModelAndView)throws Exception{

        if (null==hzqModelAndView){
            return;
        }

        //如果hzqModelAndView不为空,则将hzqModelAndView进行渲染
        if(this.viewResolvers.isEmpty()){
            return;
        }else {
            for (HZQViewResolver hzqViewResolver :viewResolvers) {
                HZQView view = hzqViewResolver.resolveViewName(hzqModelAndView.getViewName(),null);
                view.render(hzqModelAndView.getModel(),req,resp);
                return;
            }
        }

    }

    private HZQHandlerAdapter getHandlerAdapter(HZQHandlerMapping handlerMapping) {
        if (this.handlerAdapters.isEmpty()){
            return null;
        }
        HZQHandlerAdapter hzqHandlerAdapter = this.handlerAdapters.get(handlerMapping);
        if (hzqHandlerAdapter.supports(handlerMapping)){
            return hzqHandlerAdapter;
        }
        return null;
    }


    private HZQHandlerMapping getHandler(HttpServletRequest req) throws Exception {
        if(handlerMappings.isEmpty()){ return null; }
        String url = req.getRequestURI();
        String contextPath = req.getContextPath();
        url = url.replace(contextPath, "").replaceAll("/+", "/");
        System.out.println("解析的URL"+url);
        for (HZQHandlerMapping  handler : handlerMappings) {
            Matcher matcher = handler.getPattern().matcher(url);
            if(!matcher.matches()){ continue; }
            return handler;
        }
        return null;


    }

    //初始化策略
    protected void initStrategies(HZQApplicationcontext context) {
        //多文件上传的组件
        initMultipartResolver(context);
        //初始化本地语言环境
        initLocaleResolver(context);
        //初始化模板处理器
        initThemeResolver(context);
        //handlerMapping
        initHandlerMappings(context);
        //初始化参数适配器
        initHandlerAdapters(context);
        //初始化异常拦截器
        initHandlerExceptionResolvers(context);
        //初始化视图预处理器
        initRequestToViewNameTranslator(context);
        //初始化视图转换器
        initViewResolvers(context);

        initFlashMapManager(context);
    }

    private void initLocaleResolver(HZQApplicationcontext context) {
    }

    private void initMultipartResolver(HZQApplicationcontext context) {
    }

    private void initThemeResolver(HZQApplicationcontext context) {
    }

    private void initHandlerMappings(HZQApplicationcontext context) {

        String[] beanNames =  context.getBeanDefinitionNames();

        try {
            for (String beanName : beanNames) {

               Object controller =  context.getBean(beanName);

               Class<?> controllerClass = controller.getClass();

               if (!controllerClass.isAnnotationPresent(HZQController.class)){
                   continue;
               }

                String url = "";
                if(controllerClass.isAnnotationPresent(HZQRequestMapping.class)){
                    HZQRequestMapping requestMapping = controllerClass.getAnnotation(HZQRequestMapping.class);
                    url = requestMapping.value();
                }

                //获取 Method 的 url 配置
                Method[] methods = controllerClass.getMethods();

                for (Method method : methods) {

                    //没有加 RequestMapping 注解的直接忽略
                    if(!method.isAnnotationPresent(HZQRequestMapping.class)){ continue; }
                    //映射 URL
                    HZQRequestMapping requestMapping = method.getAnnotation(HZQRequestMapping.class);
                    String regex = ("/" + url + requestMapping.value().replaceAll("\\*",".*")).replaceAll("/+", "/");
                    Pattern pattern = Pattern.compile(regex);
                    handlerMappings.add(new HZQHandlerMapping(controller,method,pattern));
                    log.info("mapping " + regex + "," + method);

                }

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





    }


    private void initHandlerAdapters(HZQApplicationcontext context) {

        //把一个request请求变成一个handler,参数都是字符串的,自动匹配到handler中的形参

        //要拿到handlerMapping才能干活

        //意味着,有几个handlerMapping,就有几个HandlerAdapters

        for (HZQHandlerMapping handlerMapping : this.handlerMappings) {
            //HZQHandlerMapping HandlerAdapter 建立关联关系
            handlerAdapters.put(handlerMapping,new HZQHandlerAdapter());
        }

    }

    private void initHandlerExceptionResolvers(HZQApplicationcontext context) {
    }

    private void initRequestToViewNameTranslator(HZQApplicationcontext context) {
    }

    private void initViewResolvers(HZQApplicationcontext context) {

        //拿到模板存放目录
        String templateRoot =  context.getCongif().getProperty("templateRoot");
        String templateRootPath = this.getClass().getClassLoader().getResource(templateRoot).getFile();

        File templateRootDir = new File(templateRootPath);
        for (File file : templateRootDir.listFiles()) {
            this.viewResolvers.add(new HZQViewResolver(templateRoot));
            
        }

    }


    private void initFlashMapManager(HZQApplicationcontext context) {

    }

}

HZQHandlerMapping

package com.hezhiqin.formework.webmvc.servlet;

import com.hezhiqin.formework.annotation.HZQRequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-10-31 15:26
 */
public class HZQHandlerMapping {

    private Object controller;//保存方法对应的实例
    private Method method;//保存映射的方法
    private Pattern pattern;
    private Map<String,Integer> paramIndexMapping;//参数顺序



    /**
     *构造一个Handler基本的参数
     * @param controller
     * @param method
     */
    public HZQHandlerMapping(Object controller, Method method, Pattern pattern) {

        this.controller = controller;
        this.method = method;
        this.pattern = pattern;
        paramIndexMapping = new HashMap<String,Integer>();
        putParamIndexMapping(method);

    }



    private void putParamIndexMapping(Method method) {
        // TODO Auto-generated method stub
        //提取方法中加了注解的参数
        Annotation[] [] pa = method.getParameterAnnotations();

        for (int i = 0; i < pa.length; i++) {

            for (Annotation a : pa[i]) {
                if(a instanceof HZQRequestParam){
                    String paramName = ((HZQRequestParam) a).value();
                    if(!"".equals(paramName.trim())){
                        paramIndexMapping.put(paramName, i);
                    }
                }

            }
        }

        //提取方法中的 request 和 response 参数
        Class<?> [] paramsTypes = method.getParameterTypes();
        for (int i = 0; i < paramsTypes.length ; i ++) {
            Class<?> type = paramsTypes[i];
            if(type == HttpServletRequest.class ||
                    type == HttpServletResponse.class){
                paramIndexMapping.put(type.getName(),i);
            }

        }


    }



    public Class<?>[] getParamTypes() {
        Class<?> [] paramsTypes = method.getParameterTypes();
        return paramsTypes;
    }

    public Object getController() {
        return controller;
    }

    public void setController(Object controller) {
        this.controller = controller;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public Pattern getPattern() {
        return pattern;
    }

    public void setPattern(Pattern pattern) {
        this.pattern = pattern;
    }

    public Map<String, Integer> getParamIndexMapping() {
        return paramIndexMapping;
    }

    public void setParamIndexMapping(Map<String, Integer> paramIndexMapping) {
        this.paramIndexMapping = paramIndexMapping;
    }
}

HZQHandlerAdapter

package com.hezhiqin.formework.webmvc.servlet;

import com.hezhiqin.formework.annotation.HZQRequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-10-31 16:25
 */
public class HZQHandlerAdapter {


     public boolean supports(Object handler){
        return (handler instanceof HZQHandlerMapping);
     }


    public HZQModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
        HZQHandlerMapping handlerMapping = (HZQHandlerMapping) handler;
        Map<String,Integer> paramIndexMapping = new HashMap<String,Integer>();

        Method method  = handlerMapping.getMethod();
        //提取方法中加了注解的参数
        Annotation[] [] pa = method.getParameterAnnotations();

        for (int i = 0; i < pa.length; i++) {

            for (Annotation a : pa[i]) {
                if(a instanceof HZQRequestParam){
                    String paramName = ((HZQRequestParam) a).value();
                    if(!"".equals(paramName.trim())){
                        paramIndexMapping.put(paramName, i);
                    }
                }

            }
        }

        //提取方法中的 request 和 response 参数
        Class<?> [] paramsTypes = method.getParameterTypes();
        for (int i = 0; i < paramsTypes.length ; i ++) {
            Class<?> type = paramsTypes[i];
            if(type == HttpServletRequest.class ||
                    type == HttpServletResponse.class){
                paramIndexMapping.put(type.getName(),i);
            }

        }


        //获得方法的形参列表
        Map<String,String[]> params = request.getParameterMap();

        //实参列表
        Object [] paramValues = new Object[paramsTypes.length];



        for (Map.Entry<String, String[]> parm : params.entrySet()) {

            String value = Arrays.toString(parm.getValue()).replaceAll("\\[|\\]","")
                    .replaceAll("\\s",",");
            if(!paramIndexMapping.containsKey(parm.getKey())){continue;}
            int index = paramIndexMapping.get(parm.getKey());
            paramValues[index] = caseStringValue(value,paramsTypes[index]);



        }

        if(paramIndexMapping.containsKey(HttpServletRequest.class.getName())) {
            int reqIndex = paramIndexMapping.get(HttpServletRequest.class.getName());
            paramValues[reqIndex] = request;
        }



        if(paramIndexMapping.containsKey(HttpServletResponse.class.getName())) {
            int respIndex = paramIndexMapping.get(HttpServletResponse.class.getName());
            paramValues[respIndex] = response;
        }

        Object returnValue = method.invoke(handlerMapping.getController(),paramValues);

        if(returnValue == null || returnValue instanceof Void){ return null; }

        if (method.getReturnType()==HZQModelAndView.class){
            return (HZQModelAndView) returnValue;
        }

        return  null;
    }

    private Object caseStringValue(String value, Class<?> paramsType) {
        if (String.class  == paramsType){
            return value;
        }

        if(Integer.class == paramsType){
            return Integer.valueOf(value);
        }else if(Double.class == paramsType){
            return Double.valueOf(value);
        }else {
            if (value!=null){
                return value.toString();
            }
            return null;
        }

    }


}

HZQModelAndView

package com.hezhiqin.formework.webmvc.servlet;

import java.util.Map;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-10-31 16:28
 */
public class HZQModelAndView {

    private String viewName;
    private Map<String,?> model;

    public HZQModelAndView(String viewName) {
        this.viewName = viewName;
    }

    public HZQModelAndView(String viewName, Map<String, ?> model) {
        this.viewName = viewName;
        this.model = model;
    }

    public String getViewName() {
        return viewName;
    }

    public void setViewName(String viewName) {
        this.viewName = viewName;
    }

    public Map<String, ?> getModel() {
        return model;
    }

    public void setModel(Map<String, ?> model) {
        this.model = model;
    }
}

HZQViewResolver

package com.hezhiqin.formework.webmvc.servlet;

import java.io.File;
import java.util.Locale;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-11-01 11:48
 */
public class HZQViewResolver {

    private  File  templateRootDir;


    private  final  String DEFAULT_TEMPLATE_SUFFX = "html";


    public HZQViewResolver(String templateRoot) {
        String templateRootPath = this.getClass().getClassLoader().getResource(templateRoot).getFile();
        templateRootDir = new File(templateRootPath);
    }

    public HZQView resolveViewName(String viewName, Locale locale) throws Exception{
        //viewName 解析成文件
        if (viewName==null||"".equals(viewName)){
            return null;
        }
        viewName = viewName.endsWith(DEFAULT_TEMPLATE_SUFFX)?viewName:(viewName+".html");
        File templatefile  = new File((templateRootDir.getPath()+"/"+viewName).replaceAll("/+","/"));
        return new HZQView(templatefile);
    }

    public File getTemplateRootDir() {
        return templateRootDir;
    }

    public void setTemplateRootDir(File templateRootDir) {
        this.templateRootDir = templateRootDir;
    }


}

HZQView

package com.hezhiqin.formework.webmvc.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-11-01 11:51
 */
public class HZQView {

    private  final String DEFULAT_CONTENT_TYPE = "text/html;charset=utf-8";

    private File viewFile;

    public HZQView(File viewFile) {
        this.viewFile = viewFile;
    }

    //
    public  void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
            throws Exception{

        StringBuffer stringBuffer = new StringBuffer();

        //占位符替换成我们想要的字符
        RandomAccessFile raf = new RandomAccessFile(viewFile,"r");
        String line = null;
        while (null!=(line = raf.readLine())){
            line = new String(line.getBytes("ISO-8859-1"),"UTF-8");
            Pattern pattern = Pattern.compile("¥\\{[^\\}]+\\}",Pattern.CASE_INSENSITIVE);

            Matcher matcher = pattern.matcher(line);
            while (matcher.find()){
                String paramName = matcher.group();
                paramName = paramName.replaceAll("¥\\{|\\}","");
                Object oparamValue = model.get(paramName);
                if (null==oparamValue){
                    continue;
                }
                line = matcher.replaceFirst(makeStringForRegExp(oparamValue.toString()));

                matcher = pattern.matcher(line);
            }
            stringBuffer.append(line);
        }

        response.setCharacterEncoding("utf-8");
        response.getWriter().write(stringBuffer.toString());

    }

    //处理特殊字符
    public static String makeStringForRegExp(String str) {
        return str.replace("\\", "\\\\").replace("*", "\\*")
                .replace("+", "\\+").replace("|", "\\|")
                .replace("{", "\\{").replace("}", "\\}")
                .replace("(", "\\(").replace(")", "\\)")
                .replace("^", "\\^").replace("$", "\\$")
                .replace("[", "\\[").replace("]", "\\]")
                .replace("?", "\\?").replace(",", "\\,")
                .replace(".", "\\.").replace("&", "\\&");
    }

}

定制模板页面

first.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
	<meta charset="utf-8">
	<title>咕泡学院SpringMVC模板引擎演示</title>
</head>
<center>
	<h1>大家好,我是¥{teacher}老师<br/>欢迎大家一起来探索Spring的世界</h1>
	<h3>Hello,My name is ¥{teacher}</h3>
	<div>{data}</div>
	Token值:¥{token}
</center>
</html>

404.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>页面去火星了</title>
</head>
<body>
    <font size='25' color='red'>404 Not Found</font><br/><font color='green'><i>Copyright@GupaoEDU</i></font>
</body>
</html>

500.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>服务器好像累了</title>
</head>
<body>
    <font size='25' color='blue'>500 服务器好像有点累了,需要休息一下</font><br/>
    <b>Message:{detail}</b><br/>
    <b>StackTrace:{stackTrace}</b><br/>
    <font color='green'><i>Copyright@GupaoEDU</i></font>
</body>
</html>

具体的调用流程

1.之前的IOC和DI都已经在HZQDispathcherServlet的 init方法中实现了
用30个类高仿真提炼纯手写Spring框架_第5张图片

2.初始化9大组件。
2.1 initHandlerMappings将url和获取 Method 进行配对,
2.2 初始化参数适配器。一个HandlerMapping对应一个HZQHandlerAdapter 保存在Map handlerAdapters 容器中
2.3初始化视图转换器
将模板(html页面)保存在视图解析器里
在这里插入图片描述
用30个类高仿真提炼纯手写Spring框架_第6张图片

用30个类高仿真提炼纯手写Spring框架_第7张图片

3.网页调用时候其实是调用的HZQDispathcherServlet中的doDispather方法

在此将返回值返回至页面
用30个类高仿真提炼纯手写Spring框架_第8张图片

完成AOP配置

基础配置

用30个类高仿真提炼纯手写Spring框架_第9张图片

标题完成AOP 顶层设计

HZQAopProxy

package com.hezhiqin.formework.aop;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-11-05 14:12
 */
//默认就用JDK 动态代理
public interface HZQAopProxy {

    Object getProxy();

    Object getProxy(ClassLoader classLoader);
}

HZQJdkDynamicAopProxy

public class HZQJdkDynamicAopProxy implements  HZQAopProxy,InvocationHandler{

    private HZQAdvisedSupport advised;

    public HZQJdkDynamicAopProxy(HZQAdvisedSupport config){
        this.advised = config;
    }

    @Override
    public Object getProxy() {
        return getProxy(this.advised.getTargetClass().getClassLoader());
    }

    @Override
    public Object getProxy(ClassLoader classLoader) {
        return Proxy.newProxyInstance(classLoader,this.advised.getTargetClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        List<Object> interceptorsAndDynamicMethodMatchers = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,this.advised.getTargetClass());
        HZQMethodInvocation hzqMethodInvocation = new HZQMethodInvocation(proxy,this.advised.getTarget(),method,args,this.advised.getTargetClass(),interceptorsAndDynamicMethodMatchers);
        return hzqMethodInvocation.proceed();
    }
}

HZQAdvisedSupport

package com.hezhiqin.formework.aop.support;

import com.hezhiqin.formework.aop.aspect.HZQAfterReturningAdviceInterceptor;
import com.hezhiqin.formework.aop.aspect.HZQAfterThrowingAdviceInterceptor;
import com.hezhiqin.formework.aop.aspect.HZQMethodBeforeAdviceInterceptor;
import com.hezhiqin.formework.aop.config.HZQAopConfig;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-11-05 14:20
 */
public class HZQAdvisedSupport {

    private Object target;

    private Class<?> targetClass;


    private HZQAopConfig config;


    private Pattern pointCutClassPattern;

    private transient Map<Method, List<Object>> methodCache;

    public HZQAdvisedSupport(HZQAopConfig config) {
        this.config = config;
    }

    public Class<?> getTargetClass(){
        return this.targetClass;
    }

    public void setTargetClass(Class<?> targetClass) {
        this.targetClass = targetClass;
        parse();
    }


    public Object getTarget(){
        return this.target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) throws Exception{
        List<Object> cached = methodCache.get(method);
        if(cached==null){
            Method m = targetClass.getMethod(method.getName(),method.getParameterTypes());

            cached = methodCache.get(m);

            //底层逻辑,对代理方法进行一个兼容处理
            this.methodCache.put(m,cached);
        }

        return cached;
    }

    public boolean pointCutMatch() {
        return  pointCutClassPattern.matcher(this.targetClass.toString()).matches();
    }



    private void parse() {
        String pointCut = config.getPointCut()
                .replaceAll("\\.","\\\\.")
                .replaceAll("\\\\.\\*",".*")
                .replaceAll("\\(","\\\\(")
                .replaceAll("\\)","\\\\)");
        //pointCut=public .* com.gupaoedu.vip.spring.demo.service..*Service..*(.*)
        //玩正则,完整的匹配传入的类是否匹配切点规则
        String pointCutForClassRegex = pointCut.substring(0,pointCut.lastIndexOf("\\(") - 4);
        pointCutClassPattern = Pattern.compile("class " + pointCutForClassRegex.substring(
                pointCutForClassRegex.lastIndexOf(" ") + 1));

        try {

            methodCache = new HashMap<Method, List<Object>>();
            Pattern pattern = Pattern.compile(pointCut);



            Class aspectClass = Class.forName(this.config.getAspectClass());
            Map<String,Method> aspectMethods = new HashMap<String,Method>();
            for (Method m : aspectClass.getMethods()) {//切面的方法
                aspectMethods.put(m.getName(),m);
            }

            for (Method m : this.targetClass.getMethods()) {//切面的方法
                String methodString = m.toString();
                if (methodString.contains("throws")) {
                    methodString = methodString.substring(0, methodString.lastIndexOf("throws")).trim();
                }

                Matcher matcher = pattern.matcher(methodString);
                if(matcher.matches()){
                    //执行器链
                    List<Object> advices = new LinkedList<Object>();
                    //把每一个方法包装成 MethodInterceptor
                    //before
                    if(!(null == config.getAspectBefore() || "".equals(config.getAspectBefore()))) {
                        //创建一个Advivce
                        advices.add(new HZQMethodBeforeAdviceInterceptor(aspectMethods.get(config.getAspectBefore()),aspectClass.newInstance()));
                    }
                    //after
                    if(!(null == config.getAspectAfter() || "".equals(config.getAspectAfter()))) {
                        //创建一个Advivce
                        advices.add(new HZQAfterReturningAdviceInterceptor(aspectMethods.get(config.getAspectAfter()),aspectClass.newInstance()));
                    }
                    //afterThrowing
                    if(!(null == config.getAspectAfterThrow() || "".equals(config.getAspectAfterThrow()))) {
                        //创建一个Advivce
                        HZQAfterThrowingAdviceInterceptor throwingAdvice =
                                new HZQAfterThrowingAdviceInterceptor(
                                        aspectMethods.get(config.getAspectAfterThrow()),
                                        aspectClass.newInstance());
                        throwingAdvice.setThrowName(config.getAspectAfterThrowingName());
                        advices.add(throwingAdvice);
                    }
                    methodCache.put(m,advices);
                }

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


    }
}

HZQMethodInvocation

package com.hezhiqin.formework.aop.intercept;

import com.hezhiqin.formework.aop.aspect.HZQJoinPoint;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-11-06 13:27
 */
public class HZQMethodInvocation implements HZQJoinPoint {

    private Object proxy;
    private Method method;
    private Object target;
    private Object [] arguments;
    private List<Object> interceptorsAndDynamicMethodMatchers;
    private Class<?> targetClass;

    private Map<String, Object> userAttributes;


    //定义一个索引,从-1开始来记录当前拦截器执行的位置
    private int currentInterceptorIndex = -1;

    public HZQMethodInvocation(
            Object proxy, Object target, Method method, Object[] arguments,
            Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
        this.proxy = proxy;
        this.target = target;
        this.targetClass = targetClass;
        this.method = method;
        this.arguments = arguments;
        this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;

    }


    public Object proceed() throws Throwable {
        //	We start with an index of -1 and increment early.
        //如果Interceptor 执行完了,则执行joinPoint
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return this.method.invoke(this.target,this.arguments);
        }

        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        //如果要动态匹配joinPoint
        if (interceptorOrInterceptionAdvice instanceof HZQMethodInterceptor) {
            HZQMethodInterceptor mi =
                    (HZQMethodInterceptor) interceptorOrInterceptionAdvice;
            return mi.invoke(this);
        } else {
            //动态匹配失败时,略过当前Intercetpor,调用下一个Interceptor
            return proceed();
        }
    }

    @Override
    public Object getThis() {
        return this;
    }

    @Override
    public Object[] getArguments() {
        return arguments;
    }

    @Override
    public Method getMethod() {
        return method;
    }

    @Override
    public void setUserAttribute(String key, Object value) {
        if (value != null) {
            if (this.userAttributes == null) {
                this.userAttributes = new HashMap<String,Object>();
            }
            this.userAttributes.put(key, value);
        }
        else {
            if (this.userAttributes != null) {
                this.userAttributes.remove(key);
            }
        }
    }

    @Override
    public Object getUserAttribute(String key) {
        return (this.userAttributes != null ? this.userAttributes.get(key) : null);
    }
}

HZQMethodInterceptor

package com.hezhiqin.formework.aop.intercept;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-11-06 13:48
 */
public interface HZQMethodInterceptor {

    Object invoke(HZQMethodInvocation invocation) throws Throwable;
}

HZQAdvice

package com.hezhiqin.formework.aop.aspect;

public interface HZQAdvice {
}

HZQJoinPoint

package com.hezhiqin.formework.aop.aspect;

import java.lang.reflect.Method;

/**
 * Created by Tom on 2019/4/15.
 */
public interface HZQJoinPoint {

    Object getThis();

    Object[] getArguments();

    Method getMethod();

    void setUserAttribute(String key, Object value);

    Object getUserAttribute(String key);
}

HZQAopConfig

package com.hezhiqin.formework.aop.config;

import lombok.Data;

/**
 * @program: homeWork
 * @description: 对应配置文件
 * @author: hezhiqin
 * @create: 2019-11-06 14:44
 */
@Data
public class HZQAopConfig {

    private String pointCut;

    private String  aspectClass;

    private String  aspectBefore;

    private String  aspectAfter;

    private String  aspectAfterThrow;

    private String  aspectAfterThrowingName;

}

设计AOP 基础实现

HZQAbstractAspectAdvice

package com.hezhiqin.formework.aop.aspect;

import java.lang.reflect.Method;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-11-06 16:06
 */
public abstract  class HZQAbstractAspectAdvice implements HZQAdvice {

    private Method aspectMethod;

    private Object aspectTarget;

    public HZQAbstractAspectAdvice(Method aspectMethod, Object aspectTarget) {
        this.aspectMethod = aspectMethod;
        this.aspectTarget = aspectTarget;
    }

    protected  Object invokeAdviceMethod(HZQJoinPoint joinPoint, Object returnValue, Throwable tx)throws Throwable{
        Class<?> [] paramTypes = this.aspectMethod.getParameterTypes();
        if(null == paramTypes || paramTypes.length == 0){
            return this.aspectMethod.invoke(aspectTarget);
        }else{
            Object [] args = new Object[paramTypes.length];
            for (int i = 0; i < paramTypes.length; i ++) {
                if(paramTypes[i] == HZQJoinPoint.class){
                    args[i] = joinPoint;
                }else if(paramTypes[i] == Throwable.class){
                    args[i] = tx;
                }else if(paramTypes[i] == Object.class){
                    args[i] = returnValue;
                }
            }
            return this.aspectMethod.invoke(aspectTarget,args);
        }
    }
}

HZQMethodBeforeAdviceInterceptor

package com.hezhiqin.formework.aop.aspect;

import com.hezhiqin.formework.aop.intercept.HZQMethodInterceptor;
import com.hezhiqin.formework.aop.intercept.HZQMethodInvocation;

import java.lang.reflect.Method;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-11-06 15:58
 */
public class HZQMethodBeforeAdviceInterceptor extends HZQAbstractAspectAdvice  implements HZQMethodInterceptor {

    private HZQJoinPoint joinPoint;

    public HZQMethodBeforeAdviceInterceptor(Method aspectMethod, Object aspectTarget) {
        super(aspectMethod, aspectTarget);
    }


    private void before(Method method,Object[] args,Object target) throws Throwable{
        super.invokeAdviceMethod(this.joinPoint,null,null);

    }

    @Override
    public Object invoke(HZQMethodInvocation invocation) throws Throwable {
        this.joinPoint = invocation;
        before(invocation.getMethod(), invocation.getArguments(), invocation.getThis());
        return invocation.proceed();
    }
}

HZQAfterReturningAdviceInterceptor

package com.hezhiqin.formework.aop.aspect;

import com.hezhiqin.formework.aop.intercept.HZQMethodInterceptor;
import com.hezhiqin.formework.aop.intercept.HZQMethodInvocation;

import java.lang.reflect.Method;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-11-06 15:58
 */
public class HZQAfterReturningAdviceInterceptor extends HZQAbstractAspectAdvice implements HZQMethodInterceptor {

    private HZQJoinPoint joinPoint;

    public HZQAfterReturningAdviceInterceptor(Method aspectMethod, Object aspectTarget) {
        super(aspectMethod, aspectTarget);
    }


    private void afterReturning(Object retVal, Method method, Object[] arguments, Object aThis) throws Throwable {
        super.invokeAdviceMethod(this.joinPoint,retVal,null);
    }

    @Override
    public Object invoke(HZQMethodInvocation invocation) throws Throwable {
        Object retVal = invocation.proceed();
        this.joinPoint = invocation;
        afterReturning(retVal, invocation.getMethod(), invocation.getArguments(),invocation.getThis());
        return retVal;
    }
}

HZQAfterThrowingAdviceInterceptor

package com.hezhiqin.formework.aop.aspect;

import com.hezhiqin.formework.aop.intercept.HZQMethodInterceptor;
import com.hezhiqin.formework.aop.intercept.HZQMethodInvocation;

import java.lang.reflect.Method;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-11-06 16:00
 */
public class HZQAfterThrowingAdviceInterceptor extends HZQAbstractAspectAdvice implements HZQMethodInterceptor {


    private String throwName;

    public HZQAfterThrowingAdviceInterceptor(Method aspectMethod, Object aspectTarget) {
        super(aspectMethod, aspectTarget);
    }

    public void setThrowName(String throwName) {
        this.throwName = throwName;
    }

    @Override
    public Object invoke(HZQMethodInvocation invocation) throws Throwable {
        try {
            return invocation.proceed();
        }catch (Throwable e){
            invokeAdviceMethod(invocation,null,e.getCause());
            throw e;
        }
    }
}

接入getBean()方法

找到GPApplicationContext 的getBean()方法,我们知道getBean()中负责Bean 初始化的方法其实就是instantiateBean(),我们在初始化时就可以确定是否返回原生Bean 还是Proxy Bean。代码实现
用30个类高仿真提炼纯手写Spring框架_第10张图片
至此我们就创建了一个代理对象 在这里有一个很关键的方法,这是怕被切点的方法和LogAspect 配置的方法绑定

用30个类高仿真提炼纯手写Spring框架_第11张图片

 private void parse() {
        String pointCut = config.getPointCut()
                .replaceAll("\\.","\\\\.")
                .replaceAll("\\\\.\\*",".*")
                .replaceAll("\\(","\\\\(")
                .replaceAll("\\)","\\\\)");
        //pointCut=public .* com.gupaoedu.vip.spring.demo.service..*Service..*(.*)
        //玩正则,完整的匹配传入的类是否匹配切点规则
        String pointCutForClassRegex = pointCut.substring(0,pointCut.lastIndexOf("\\(") - 4);
        pointCutClassPattern = Pattern.compile("class " + pointCutForClassRegex.substring(
                pointCutForClassRegex.lastIndexOf(" ") + 1));

        try {

            methodCache = new HashMap<Method, List<Object>>();
            Pattern pattern = Pattern.compile(pointCut);



            Class aspectClass = Class.forName(this.config.getAspectClass());
            Map<String,Method> aspectMethods = new HashMap<String,Method>();
            for (Method m : aspectClass.getMethods()) {//切面的方法
                aspectMethods.put(m.getName(),m);
            }

            for (Method m : this.targetClass.getMethods()) {//切面的方法
                String methodString = m.toString();
                if (methodString.contains("throws")) {
                    methodString = methodString.substring(0, methodString.lastIndexOf("throws")).trim();
                }

                Matcher matcher = pattern.matcher(methodString);
                if(matcher.matches()){
                    //执行器链
                    List<Object> advices = new LinkedList<Object>();
                    //把每一个方法包装成 MethodInterceptor
                    //before
                    if(!(null == config.getAspectBefore() || "".equals(config.getAspectBefore()))) {
                        //创建一个Advivce
                        advices.add(new HZQMethodBeforeAdviceInterceptor(aspectMethods.get(config.getAspectBefore()),aspectClass.newInstance()));
                    }
                    //after
                    if(!(null == config.getAspectAfter() || "".equals(config.getAspectAfter()))) {
                        //创建一个Advivce
                        advices.add(new HZQAfterReturningAdviceInterceptor(aspectMethods.get(config.getAspectAfter()),aspectClass.newInstance()));
                    }
                    //afterThrowing
                    if(!(null == config.getAspectAfterThrow() || "".equals(config.getAspectAfterThrow()))) {
                        //创建一个Advivce
                        HZQAfterThrowingAdviceInterceptor throwingAdvice =
                                new HZQAfterThrowingAdviceInterceptor(
                                        aspectMethods.get(config.getAspectAfterThrow()),
                                        aspectClass.newInstance());
                        throwingAdvice.setThrowName(config.getAspectAfterThrowingName());
                        advices.add(throwingAdvice);
                    }
                    methodCache.put(m,advices);
                }

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


    }

那么在调用时会调用 HZQJdkDynamicAopProxy 中的 invoke方法
用30个类高仿真提炼纯手写Spring框架_第12张图片

这里巧妙在proceed的执行顺序上

1.先在HZQMethodInvocation定义一个索引

	//定义一个索引,从-1开始来记录当前拦截器执行的位置
    private int currentInterceptorIndex = -1;



	public Object proceed() throws Throwable {
        //	We start with an index of -1 and increment early.
        //如果Interceptor 执行完了,则执行joinPoint
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return this.method.invoke(this.target,this.arguments);
        }

        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        //如果要动态匹配joinPoint
        if (interceptorOrInterceptionAdvice instanceof HZQMethodInterceptor) {
            HZQMethodInterceptor mi =
                    (HZQMethodInterceptor) interceptorOrInterceptionAdvice;
            return mi.invoke(this);
        } else {
            //动态匹配失败时,略过当前Intercetpor,调用下一个Interceptor
            return proceed();
        }
    }

可以Debug看下proceed的执行顺序,下面是图解
用30个类高仿真提炼纯手写Spring框架_第13张图片
打完收工 看一下效果
用30个类高仿真提炼纯手写Spring框架_第14张图片
后台输出
用30个类高仿真提炼纯手写Spring框架_第15张图片

你可能感兴趣的:(Spring源码剖析)