1、ControllerDefinition
javapackage 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
javapackage 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); } } } } } } } }
项目实战:组件扫描(4)-筛选带有RequestMapping注解的bean实例
丁总学Java2023-11-08 17:03
相关推荐
morris1311 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段七星静香26 分钟前
laravel chunkById 分块查询 使用时的问题Jacob程序员27 分钟前
java导出word文件(手绘)ZHOUPUYU27 分钟前
IntelliJ IDEA超详细下载安装教程(附安装包)stewie630 分钟前
在IDEA中使用GitElaine2023911 小时前
06 网络编程基础G丶AEOM1 小时前
分布式——BASE理论落落鱼20131 小时前
tp接口 入口文件 500 错误原因想要打 Acm 的小周同学呀1 小时前
LRU缓存算法镰刀出海1 小时前
Recyclerview缓存原理