JavaEE-自定义SSM-编写核心- my spring bean工厂(IoC、DI)

3.4 my spring bean工厂(IoC、DI)

  • 加载类
  • 解析类
  • 获得类

3.4.0 分析

3.4.1 扫描指定包下的所有类

package com.czxy.bean;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;


public class MyBeanFactory {

    private static String classpath = new File(MyBeanFactory.class.getClassLoader().getResource("").getPath()).getPath();

    /**
     * 初始化方法
     * @param packageName
     */
    public static void init(String packageName) {
        //1 扫描 指定包 下面的所有内容(接口、类)
        // 1.1 获得 指定包 所在的位置,以文件File形式
        File packageFile = packageToFile(packageName);
        // 1.2 根据 包的位置 获得所有的类
        List<String> classNameList = getAllClassName(packageFile);
        System.out.println(classNameList);

        //2 处理类
    }


    /**
     * com.czxy --> com/czxy
     * @param packageName
     * @return
     */
    private static File packageToFile(String packageName) {
        return new File(classpath , packageName.replace(".", "/"));
    }

    /**
     * 获得指定包所有内容,如果是类
     * @param dir
     * @return
     */
    private static List<String> getAllClassName(File dir) {
        List<String> list = new ArrayList<>();
        if(dir == null) {
            return list;
        }
        for(File file: Objects.requireNonNull(dir.listFiles())) {
            if(file.isFile()) {
                list.add(pathToClassName(file.getPath()));
            } else {
                List<String> subList = getAllClassName(file);
                list.addAll(subList);
            }
        }
        return list;
    }

    /**
     *
     * @param path
     * @return A.B.C
     */
    private static String pathToClassName(String path) {
        // 取消前缀
        String newPath = path.replace(classpath + "\\", "");
        if(newPath.endsWith(".class")) {
            //处理类
            String tempPath = newPath.replace("\\", ".");
            return tempPath.substring(0, tempPath.length() - 6);
        } else {
            return newPath;
        }
    }
}

在程序运行时,执行bean工厂初始化

3.4.2 创建bean实例(IoC)

Bean工厂

*

java 复制代码
package com.czxy.bean;

import com.czxy.annotation.MyMapper;
import com.czxy.annotation.MyRestController;
import com.czxy.annotation.MyService;
import com.czxy.boot.MybatisHandler;

import java.io.File;
import java.lang.reflect.Proxy;
import java.util.*;


public class MyBeanFactory {

    private static String classpath = new File(MyBeanFactory.class.getClassLoader().getResource("").getPath()).getPath();

    private static Map<Class, Object> objectMap = new HashMap<>();

    /**
     * 初始化方法
     * @param packageName
     */
    public static void init(String packageName) {
        try {
            //1 扫描 指定包 下面的所有内容(接口、类)
            // 1.1 获得 指定包 所在的位置,以文件File形式
            File packageFile = packageToFile(packageName);
            // 1.2 根据 包的位置 获得所有的类
            List<String> classNameList = getAllClassName(packageFile);

            //2 处理类:创建实例(IoC)
            // 2.1 遍历所有的类文件
            for(String className: classNameList) {
                // 2.2 获得类对应Class对象
                Class beanClass = Class.forName(className);

                // 2.3 根据注解创建实例
                // 2.3.1 如果有@RestController,创建controller
                boolean isController = beanClass.isAnnotationPresent(MyRestController.class);
                if(isController) {
                    // 直接创建对象
                    objectMap.put(beanClass, beanClass.newInstance());

                }
                // 2.3.2 如果有@Service,创建Service,需要获得接口
                boolean isService = beanClass.isAnnotationPresent(MyService.class);
                if(isService) {
                    // 如果有接口,接口-->实现类。 如果没有接口, 实现类-->实现类
                    Class[] interfaces = beanClass.getInterfaces();
                    if(interfaces.length == 0) {
                        // 没有接口
                        objectMap.put(beanClass, beanClass.newInstance());
                    } else {
                        // 有接口
                        objectMap.put(interfaces[0], beanClass.newInstance());
                    }

                }
                // 2.3.3 如果有@Mapper,创建代理
                boolean isMapper = beanClass.isAnnotationPresent(MyMapper.class);
                if(isMapper) {
                    // 创建Map对应的代理类
                    // 1) 参数
                    // 1.1) 类加载器
                    ClassLoader loader = MyBeanFactory.class.getClassLoader();
                    // 1.2) 接口们
                    Class[] interfaces = new Class[] {beanClass};
                    // 1.3) 处理类
                    MybatisHandler mybatisHandler = new MybatisHandler(beanClass);
                    // 2) 工具创建
                    objectMap.put(beanClass, Proxy.newProxyInstance(loader, interfaces, mybatisHandler));

                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        System.out.println(objectMap);
    }


    /**
     * com.czxy --> com/czxy
     * @param packageName
     * @return
     */
    private static File packageToFile(String packageName) {
        return new File(classpath , packageName.replace(".", "/"));
    }

    /**
     * 获得指定包所有内容,如果是类
     * @param dir
     * @return
     */
    private static List<String> getAllClassName(File dir) {
        List<String> list = new ArrayList<>();
        if(dir == null) {
            return list;
        }
        for(File file: Objects.requireNonNull(dir.listFiles())) {
            if(file.isFile()) {
                list.add(pathToClassName(file.getPath()));
            } else {
                List<String> subList = getAllClassName(file);
                list.addAll(subList);
            }
        }
        return list;
    }

    /**
     *
     * @param path
     * @return A.B.C
     */
    private static String pathToClassName(String path) {
        // 取消前缀
        String newPath = path.replace(classpath + "\\", "");
        if(newPath.endsWith(".class")) {
            //处理类
            String tempPath = newPath.replace("\\", ".");
            return tempPath.substring(0, tempPath.length() - 6);
        } else {
            return newPath;
        }
    }
}
  • 代理类处理类

    java 复制代码
    package com.czxy.boot;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    
    public class MybatisHandler implements InvocationHandler {
        private Class beanClass;
        public MybatisHandler(Class beanClass) {
            this.beanClass = beanClass;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("代理类的处理类执行了");
            //1 获得方法名
            String methodName = method.getName();
            //2 处理 toString 方法
            if("toString".equals(methodName)) {
                return "myProxy";
            }
            return null;
        }
    }

3.4.3 依赖关系

package com.czxy.bean;

import com.czxy.annotation.MyMapper;

import com.czxy.annotation.MyRestController;

import com.czxy.annotation.MyService;

import com.czxy.boot.MybatisHandler;

import javax.annotation.Resource;

import javax.annotation.Resources;

import java.io.File;

import java.lang.reflect.Field;

import java.lang.reflect.Proxy;

import java.util.*;

public class MyBeanFactory {

private static String classpath = new File(MyBeanFactory.class.getClassLoader().getResource("").getPath()).getPath();

private static Map<Class, Object> objectMap = new HashMap<>();

/**
 * 初始化方法
 * @param packageName
 */
public static void init(String packageName) {
    try {
        //1 扫描 指定包 下面的所有内容(接口、类)
        // 1.1 获得 指定包 所在的位置,以文件File形式
        File packageFile = packageToFile(packageName);
        // 1.2 根据 包的位置 获得所有的类
        List<String> classNameList = getAllClassName(packageFile);

        //2 处理类:创建实例(IoC)
        // 2.1 遍历所有的类文件
        for(String className: classNameList) {
            // 2.2 获得类对应Class对象
            Class beanClass = Class.forName(className);

            // 2.3 根据注解创建实例
            // 2.3.1 如果有@RestController,创建controller
            boolean isController = beanClass.isAnnotationPresent(MyRestController.class);
            if(isController) {
                // 直接创建对象
                objectMap.put(beanClass, beanClass.newInstance());
            }
            // 2.3.2 如果有@Service,创建Service,需要获得接口
            boolean isService = beanClass.isAnnotationPresent(MyService.class);
            if(isService) {
                // 如果有接口,接口-->实现类。 如果没有接口, 实现类-->实现类
                Class[] interfaces = beanClass.getInterfaces();
                if(interfaces.length == 0) {
                    // 没有接口
                    objectMap.put(beanClass, beanClass.newInstance());
                } else {
                    // 有接口
                    objectMap.put(interfaces[0], beanClass.newInstance());
                }
            }
            // 2.3.3 如果有@Mapper,创建代理
            boolean isMapper = beanClass.isAnnotationPresent(MyMapper.class);
            if(isMapper) {
                // 创建Map对应的代理类
                // 1) 参数
                // 1.1) 类加载器
                ClassLoader loader = MyBeanFactory.class.getClassLoader();
                // 1.2) 接口们
                Class[] interfaces = new Class[] {beanClass};
                // 1.3) 处理类
                MybatisHandler mybatisHandler = new MybatisHandler(beanClass);
                // 2) 工具创建
                objectMap.put(beanClass, Proxy.newProxyInstance(loader, interfaces, mybatisHandler));

            }
        }

        //3 处理类:依赖注入
        // 2.1 变量ObjectMap
        for(Map.Entry<Class, Object> entry : objectMap.entrySet()) {
            // 获得map中对象对应的Class
            Class beanClass = entry.getValue().getClass();
            // 2.2 获得所有的字段(含私有)
            Field[] fieldList = beanClass.getDeclaredFields();
            // 2.3 遍历字段
            for(Field field: fieldList) {
                // 2.4 判断字段是否有@Resource
                boolean isResource = field.isAnnotationPresent(Resource.class);
                if(isResource) {
                    // 2.5 如果有注解,获得类型
                    Class<?> fieldType = field.getType();
                    // 2.6 根据类型,从objectMap获得对应的对象
                    Object obj = objectMap.get(fieldType);
                    // 2.7 设置访问权限
                    field.setAccessible(true);
                    // 2.8 设置对象
                    field.set(entry.getValue(), obj);
                }
            }
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

    System.out.println(objectMap);
}


/**
 * com.czxy --> com/czxy
 * @param packageName
 * @return
 */
private static File packageToFile(String packageName) {
    return new File(classpath , packageName.replace(".", "/"));
}

/**
 * 获得指定包所有内容,如果是类
 * @param dir
 * @return
 */
private static List<String> getAllClassName(File dir) {
    List<String> list = new ArrayList<>();
    if(dir == null) {
        return list;
    }
    for(File file: Objects.requireNonNull(dir.listFiles())) {
        if(file.isFile()) {
            list.add(pathToClassName(file.getPath()));
        } else {
            List<String> subList = getAllClassName(file);
            list.addAll(subList);
        }
    }
    return list;
}

/**
 *
 * @param path
 * @return A.B.C
 */
private static String pathToClassName(String path) {
    // 取消前缀
    String newPath = path.replace(classpath + "\\", "");
    if(newPath.endsWith(".class")) {
        //处理类
        String tempPath = newPath.replace("\\", ".");
        return tempPath.substring(0, tempPath.length() - 6);
    } else {
        return newPath;
    }
}

}

相关推荐
yufei-coder5 小时前
掌握 C# 中的 LINQ(语言集成查询)
windows·vscode·c#·visual studio
编程、小哥哥6 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
立秋67899 小时前
Python的defaultdict详解
服务器·windows·python
Indigo_code9 小时前
【数据结构】【链表代码】合并有序链表
数据结构·windows·链表
暮雪倾风9 小时前
【WPF开发】超级详细的“文件选择”(附带示例工程)
windows·wpf
何中应11 小时前
如何使用CMD命令启动应用程序(二)
windows·桌面应用·batch命令
wxin_VXbishe11 小时前
springboot合肥师范学院实习实训管理系统-计算机毕业设计源码31290
java·spring boot·python·spring·servlet·django·php
OEC小胖胖12 小时前
Spring Boot + MyBatis 项目中常用注解详解(万字长篇解读)
java·spring boot·后端·spring·mybatis·web
sukalot12 小时前
windows C++-使用任务和 XML HTTP 请求进行连接(一)
c++·windows
落落落sss12 小时前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis