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<String, Method> 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<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内部所有的fieldField[] 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")) { //排除掉接口、注解....,只关心classif (!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);}}}}}}}
}