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


    1、ControllerDefinition

    1. package com.csdn.mymvc.core;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. import java.lang.reflect.Method;
    6. import java.util.HashMap;
    7. import java.util.Map;
    8. //假设有一个uri是:/fruit/index
    9. @Data
    10. @NoArgsConstructor
    11. @AllArgsConstructor
    12. public class ControllerDefinition {
    13. private String requestMapping;
    14. private Object controllerBean;
    15. private Map methodMappingMap = new HashMap<>();
    16. }

    2、 ComponentScan

    1. package com.csdn.mymvc.core;
    2. import com.csdn.mymvc.annotation.*;
    3. import java.io.File;
    4. import java.lang.annotation.Annotation;
    5. import java.lang.reflect.Field;
    6. import java.lang.reflect.InvocationTargetException;
    7. import java.lang.reflect.Modifier;
    8. import java.util.*;
    9. public class ComponentScan {
    10. public static Map beanFactory = new HashMap<>();
    11. public static Map controllerBeanMap = new HashMap<>();
    12. static String path = null;
    13. static {
    14. //分析文件夹
    15. path = ComponentScan.class.getClassLoader().getResource("").getPath();
    16. // /F:/IdeaProjects/workspace/review/pro13-fruit-DispatcherServlet/target/
    17. // pro13-fruit-DispatcherServlet-1.0-SNAPSHOT/WEB-INF/classes/
    18. //计算机的硬盘根目录是 / ,不论是什么操作系统。只是微软人为的分出盘符的概念
    19. //System.out.println(path);
    20. path = path.substring(1);
    21. //System.out.println(path);
    22. // F:/IdeaProjects/workspace/review/pro13-fruit-DispatcherServlet/target
    23. // /pro13-fruit-DispatcherServlet-1.0-SNAPSHOT/WEB-INF/classes/
    24. File rootDir = new File(path);
    25. //开始解析文件夹 - 组件扫描工作开始
    26. try {
    27. //第 1 步:扫描类路径,解析出所有的bean实例,存放到IOC容器中(beanFactory)
    28. parseFile(rootDir);
    29. beanFactory.values().forEach(System.out::println);
    30. //第 2 步:经过第 1 步,所有的bean实例已经创建就绪,但是bean和bean之间的依赖关系没有注入(Injection)
    31. //本步骤实现 注入依赖关系
    32. beanFactory.values().forEach(bean -> {
    33. //获取bean内部所有的field
    34. Field[] fields = bean.getClass().getDeclaredFields();
    35. //获取每一个field上的注解信息
    36. Arrays.stream(fields)
    37. .filter(field -> field.getDeclaredAnnotation(Autowire.class) != null)
    38. .forEach(field -> {
    39. //获取这个字段的类型的名称
    40. String fieldTypeName = field.getType().getName();
    41. //System.out.println(fieldTypeName);
    42. Object filedValue = beanFactory.values().stream().filter(instance -> {
    43. return field.getType().isAssignableFrom(instance.getClass());
    44. }).findFirst().orElseThrow(() -> new RuntimeException(fieldTypeName + "装配失败!"));
    45. try {
    46. field.setAccessible(true);
    47. field.set(bean, filedValue);
    48. } catch (IllegalAccessException e) {
    49. throw new RuntimeException(e);
    50. }
    51. });
    52. });
    53. //第 3 步:经过前两个步骤:IOC容器中已经准备好了所有的bean实例。并且bean实例之间的依赖关系也注入完成
    54. //这一步需要实现的是:uri是:/fruit/index 我们需要实现的是将uri中的两个标识分别映射到具体的controller实例以及controller方法上去
    55. //简单讲,这一步需要完成将每一个Controller都要存放到controllerBeanMap中
    56. beanFactory.values().stream()
    57. .filter(bean -> bean.getClass().getDeclaredAnnotation(RequestMapping.class) != null)
    58. .forEach(bean->{
    59. String requestMapping = bean.getClass().getDeclaredAnnotation(RequestMapping.class).value();
    60. Object controllerBean = bean;
    61. //开始分析bean中的每一个方法
    62. });
    63. //System.out.println(beanFactory);
    64. } catch (ClassNotFoundException e) {
    65. throw new RuntimeException(e);
    66. } catch (InvocationTargetException e) {
    67. throw new RuntimeException(e);
    68. } catch (NoSuchMethodException e) {
    69. throw new RuntimeException(e);
    70. } catch (InstantiationException e) {
    71. throw new RuntimeException(e);
    72. } catch (IllegalAccessException e) {
    73. throw new RuntimeException(e);
    74. }
    75. }
    76. private static void parseFile(File file) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    77. if (file.exists()) {
    78. if (file.isDirectory()) {
    79. //获取所有的子目录
    80. File[] childFiles = file.listFiles();
    81. for (File childFile : childFiles) {
    82. parseFile(childFile);
    83. }
    84. } else {
    85. String absPath = file.getAbsolutePath();
    86. //System.out.println(absPath);
    87. String fullClassPath = absPath.substring(path.length());
    88. //System.out.println(fullClassPath);
    89. if (fullClassPath.endsWith(".class")) {
    90. String fullClassPathName = fullClassPath.substring(0, fullClassPath.length() - ".class".length());
    91. //System.out.println(fullClassPathName);
    92. String fullClassName = fullClassPathName.replaceAll("\\\\", ".");
    93. //System.out.println(fullClassName);
    94. Class clazz = Class.forName(fullClassName);
    95. //System.out.println(clazz.toString());
    96. if (clazz.toString().startsWith("class")) { //排除掉接口、注解....,只关心class
    97. if (!Modifier.isAbstract(clazz.getModifiers())) { //排除掉抽象类
    98. Optional optional = Arrays.stream(clazz.getDeclaredAnnotations()).filter(annotation -> {
    99. return (annotation instanceof Controller || annotation instanceof Service || annotation instanceof Repository);
    100. }).findFirst();
    101. if (!optional.isEmpty()) {
    102. Object bean = clazz.getDeclaredConstructor().newInstance();
    103. beanFactory.put(fullClassName, bean);
    104. }
    105. }
    106. }
    107. }
    108. }
    109. }
    110. }
    111. }

  • 相关阅读:
    【电源专题】电源芯片封装的选择
    夏日小风扇(.html实现)——小太阳给她带去凉爽
    Linux中的库(静态库和动态库)详解
    【elasticsearch】使用自建证书搭建elasticsearch8.0.1集群
    麒麟KYLINIOS软件仓库搭建01-新创建软件仓库服务器
    unity学习 --- 地形
    Acwing 802. 区间和
    JAVA毕业设计冠军体育用品购物网站计算机源码+lw文档+系统+调试部署+数据库
    大咖说*计算讲谈社|如何提出关键问题?
    MySQL使用SHOW PROCESSLIST 详解
  • 原文地址:https://blog.csdn.net/m0_65152767/article/details/134291054