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
相关推荐
YDS8294 分钟前
DeepSeek RAG&MCP + Agent智能体项目 —— 集成ELK日志管理系统和Prometheus监控系统骄马之死7 小时前
SpringMVC + SpringBoot 核心知识点总结郑洁文9 小时前
基于Spring Boot的流浪动物救助网站螺丝钉code9 小时前
JAVA项目 Claude code CLAUDE.md 到底应该怎么写摇滚侠11 小时前
Maven 入门+高深 单一架构案例 54-59VidDown11 小时前
Webhook 调试器:让第三方回调“原形毕露”折哥的程序人生 · 物流技术专研11 小时前
Java 23 种设计模式:从踩坑到精通 | 原型模式 —— 克隆对象,深拷贝与浅拷贝的坑你踩过吗?装不满的克莱因瓶11 小时前
基于 OpenResty 扩展开发实现动态服务注册与发现能力程序员小羊!11 小时前
06Java 异常机制与常用类weixin_5231853212 小时前
Java基础知识总结(四):引用数据类型与参数传递机制