Project practice: component scanning (4) – filtering bean instances with RequestMapping annotations

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;
//Suppose there is a 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 {
        //Analyze folder
        path = ComponentScan.class.getClassLoader().getResource("").getPath();
        // /F:/IdeaProjects/workspace/review/pro13-fruit-DispatcherServlet/target/
        // pro13-fruit-DispatcherServlet-1.0-SNAPSHOT/WEB-INF/classes/
        //The root directory of the computer's hard disk is /, no matter what operating system it is. It's just Microsoft's artificial concept of dividing drive letters.
        //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);
        //Start parsing the folder - component scanning begins
        try {
            //Step 1: Scan the class path, parse out all bean instances, and store them in the IOC container (beanFactory)
            parseFile(rootDir);
            beanFactory.values().forEach(System.out::println);
            //Step 2: After step 1, all bean instances have been created, but the dependencies between beans have not been injected (Injection)
            //This step implements injecting dependencies
            beanFactory.values().forEach(bean -> {
                //Get all fields inside the bean
                Field[] fields = bean.getClass().getDeclaredFields();
                //Get the annotation information on each field
                Arrays.stream(fields)
                        .filter(field -> field.getDeclaredAnnotation(Autowire.class) != null)
                        .forEach(field -> {
                            //Get the name of the type of this 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 + "Assembly failed!"));

                            try {
                                field.setAccessible(true);
                                field.set(bean, filedValue);
                            } catch (IllegalAccessException e) {
                                throw new RuntimeException(e);
                            }
                        });
            });

            //Step 3: After the first two steps: all bean instances have been prepared in the IOC container. And the dependencies between bean instances are also injected.
            //What needs to be implemented in this step is: uri is:/fruit/index What we need to achieve is to map the two identifiers in the uri to specific controller instances and controller methods.
            //To put it simply, this step needs to be completed to store each Controller in the 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;
                        //Start analyzing each method in the 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()) {
                //Get all subdirectories
                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")) { //Exclude interfaces and annotations...., only care about class

                        if (!Modifier.isAbstract(clazz.getModifiers())) { //Exclude abstract classes

                            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);
                            }
                        }
                    }
                }
            }
        }
    }
}

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Java Skill TreeHomepageOverview 139,158 people are learning the system