项目实战:组件扫描(4)-筛选带有RequestMapping注解的bean实例

1、ControllerDefinition

java 复制代码
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<String, Method> methodMappingMap = new HashMap<>();
}

2、 ComponentScan

java 复制代码
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<String, Object> beanFactory = new HashMap<>();
    public static Map<String, ControllerDefinition> 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->{
                        String requestMapping = bean.getClass().getDeclaredAnnotation(RequestMapping.class).value();
                        Object controllerBean = bean;
                        //开始分析bean中的每一个方法
                    });

            //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<Annotation> 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);
                            }
                        }
                    }
                }
            }
        }
    }
}
相关推荐
morris1311 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
七星静香26 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员27 分钟前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU27 分钟前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie630 分钟前
在IDEA中使用Git
java·git
Elaine2023911 小时前
06 网络编程基础
java·网络
G丶AEOM1 小时前
分布式——BASE理论
java·分布式·八股
落落鱼20131 小时前
tp接口 入口文件 500 错误原因
java·开发语言
想要打 Acm 的小周同学呀1 小时前
LRU缓存算法
java·算法·缓存
镰刀出海1 小时前
Recyclerview缓存原理
java·开发语言·缓存·recyclerview·android面试