项目实战:组件扫描(5)-解析带有GetMapping或PostMapping的方法最后封装成ControllerDefinition

项目实战:组件扫描(5)-解析带有GetMapping或PostMapping的方法最后封装成ControllerDefinition_第1张图片 

1、ControllerDefinition  

package com.csdn.mymvc.core;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
//假设有一个uri是:/fruit/index
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ControllerDefinition {
    private String requestMapping;
    private Object controllerBean;
    private Map methodMappingMap = new HashMap<>();
}

2、ComponentScan

package com.csdn.mymvc.core;
import com.csdn.mymvc.annotation.*;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.*;
public class ComponentScan {
    public static Map beanFactory = new HashMap<>();
    public static Map controllerBeanMap = new HashMap<>();
    static String path = null;
    static {
        //分析文件夹
        path = ComponentScan.class.getClassLoader().getResource("").getPath();
        //  /F:/IdeaProjects/workspace/review/pro13-fruit-DispatcherServlet/target/
        //  pro13-fruit-DispatcherServlet-1.0-SNAPSHOT/WEB-INF/classes/
        //计算机的硬盘根目录是 / ,不论是什么操作系统。只是微软人为的分出盘符的概念
        //System.out.println(path);
        path = path.substring(1);
        //System.out.println(path);
        //   F:/IdeaProjects/workspace/review/pro13-fruit-DispatcherServlet/target
        //   /pro13-fruit-DispatcherServlet-1.0-SNAPSHOT/WEB-INF/classes/
        File rootDir = new File(path);
        //开始解析文件夹 - 组件扫描工作开始
        try {
            //第 1 步:扫描类路径,解析出所有的bean实例,存放到IOC容器中(beanFactory)
            parseFile(rootDir);
            beanFactory.values().forEach(System.out::println);
            //第 2 步:经过第 1 步,所有的bean实例已经创建就绪,但是bean和bean之间的依赖关系没有注入(Injection)
            //本步骤实现 注入依赖关系
            beanFactory.values().forEach(bean -> {
                //获取bean内部所有的field
                Field[] fields = bean.getClass().getDeclaredFields();
                //获取每一个field上的注解信息
                Arrays.stream(fields)
                        .filter(field -> field.getDeclaredAnnotation(Autowire.class) != null)
                        .forEach(field -> {
                            //获取这个字段的类型的名称
                            String fieldTypeName = field.getType().getName();
                            //System.out.println(fieldTypeName);
                            Object filedValue = beanFactory.values().stream().filter(instance -> {
                                return field.getType().isAssignableFrom(instance.getClass());
                            }).findFirst().orElseThrow(() -> new RuntimeException(fieldTypeName + "装配失败!"));

                            try {
                                field.setAccessible(true);
                                field.set(bean, filedValue);
                            } catch (IllegalAccessException e) {
                                throw new RuntimeException(e);
                            }
                        });
            });

            //第 3 步:经过前两个步骤:IOC容器中已经准备好了所有的bean实例。并且bean实例之间的依赖关系也注入完成
            //这一步需要实现的是:uri是:/fruit/index    我们需要实现的是将uri中的两个标识分别映射到具体的controller实例以及controller方法上去
            //简单讲,这一步需要完成将每一个Controller都要存放到controllerBeanMap中
            beanFactory.values().stream()
                    .filter(bean -> bean.getClass().getDeclaredAnnotation(RequestMapping.class) != null)
                    .forEach(bean->{

                        ControllerDefinition controllerDefinition = new ControllerDefinition();

                        String requestMapping = bean.getClass().getDeclaredAnnotation(RequestMapping.class).value();
                        Object controllerBean = bean;

                        controllerDefinition.setRequestMapping(requestMapping);
                        controllerDefinition.setControllerBean(controllerBean);
                        //开始分析bean中的每一个方法
                        Arrays.stream(bean.getClass().getDeclaredMethods()).forEach(method -> {

                            GetMapping getMappingAnnotation = method.getDeclaredAnnotation(GetMapping.class);
                            String methodMapping = null;
                            if (getMappingAnnotation != null) {
                                methodMapping = getMappingAnnotation.value();
                                methodMapping = "get_" + methodMapping;
                            }
                            PostMapping postMappingAnnotation = method.getDeclaredAnnotation(PostMapping.class);
                            if (postMappingAnnotation != null) {
                                methodMapping = postMappingAnnotation.value();
                                methodMapping = "post_" + methodMapping;
                            }
                            if (methodMapping != null) {
                                controllerDefinition.getMethodMappingMap().put(methodMapping, method);
                            }
                        });
                        //将这个controllerDefinition存放到专门的Controller容器中
                        controllerBeanMap.put(requestMapping, controllerDefinition);
                    });
            System.out.println(beanFactory);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
    private static void parseFile(File file) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        if (file.exists()) {
            if (file.isDirectory()) {
                //获取所有的子目录
                File[] childFiles = file.listFiles();
                for (File childFile : childFiles) {
                      parseFile(childFile);
                }
            } else {
                String absPath = file.getAbsolutePath();
                //System.out.println(absPath);
                String fullClassPath = absPath.substring(path.length());
                //System.out.println(fullClassPath);
                if (fullClassPath.endsWith(".class")) {
                    String fullClassPathName = fullClassPath.substring(0, fullClassPath.length() - ".class".length());
                    //System.out.println(fullClassPathName);
                    String fullClassName = fullClassPathName.replaceAll("\\\\", ".");
                    //System.out.println(fullClassName);
                    Class clazz = Class.forName(fullClassName);
                    //System.out.println(clazz.toString());
                    if (clazz.toString().startsWith("class")) {  //排除掉接口、注解....,只关心class

                        if (!Modifier.isAbstract(clazz.getModifiers())) {   //排除掉抽象类

                            Optional optional = Arrays.stream(clazz.getDeclaredAnnotations()).filter(annotation -> {
                                return (annotation instanceof Controller || annotation instanceof Service || annotation instanceof Repository);
                            }).findFirst();

                            if (!optional.isEmpty()) {
                                Object bean = clazz.getDeclaredConstructor().newInstance();
                                beanFactory.put(fullClassName, bean);
                            }
                        }
                    }
                }
            }
        }
    }
}

项目实战:组件扫描(5)-解析带有GetMapping或PostMapping的方法最后封装成ControllerDefinition_第2张图片

你可能感兴趣的:(#,IOC_MVC,java,stream,filter,getClass,forEach,IOC)