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

news2024/11/16 11:38:03

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工厂

在这里插入图片描述
*

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

  • 代理类处理类

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

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1415243.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面向Java开发者的ChatGPT提示词工程(11)扩写

什么是扩写&#xff1f; 扩写是指将较短的文本交给GPT生成更长的文本。比如&#xff1a;根据一组基本指令&#xff0c;写出一封完整的电子邮件&#xff1b;或者根据一系列主题&#xff0c;创作出一篇包含这些主题的文章。 这样的技术&#xff0c;有着广阔的应用场景&#xff…

【JavaEE】传输层网络协议

传输层网络协议 1. UDP协议 1.1 特点 面向数据报&#xff08;DatagramSocket&#xff09;数据报大小限制为64k全双工不可靠传输有接收缓冲区&#xff0c;无发送缓冲区 UDP的特点&#xff0c;我理解起来就是工人组成的**“人工传送带”**&#xff1a; 面向数据报&#xff08;…

CMake简明教程 笔记

推荐B站视频&#xff1a;1.1 Cmake构建项目的流程_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1xa4y1R7vT?p1&vd_sourcea934d7fc6f47698a29dac90a922ba5a3 >>目录 1&#xff09;CMake初体验 CMake构建流程Windows下使用CMake构建项目Linux下使用CMake构…

vue3使用@imengyu/vue3-context-menu完成antv/x6右键菜单

1、下载插件&#xff1a; npm i imengyu/vue3-context-menu1.3.6 2、在页面中引入并使用插件&#xff1a; <script setup> import ContextMenu from "imengyu/vue3-context-menu";graph.on("node:contextmenu", ({ e, x, y, cell, view }) > {ha…

本地磁盘消失了怎么办?本地磁盘不见了如何恢复

本地磁盘消失了怎么办&#xff1f;本地磁盘不见了如何恢复&#xff1f;在使用计算机过程中&#xff0c;有时候会遇到本地磁盘突然消失的情况&#xff0c;这让许多用户感到困扰。本文将针对这个问题进行探讨&#xff0c;介绍一些常见的磁盘恢复方法&#xff0c;帮助用户尽快解决…

【c++】类对象模型

1.如何计算类对象的大小 class A { public:void PrintA(){cout<<_a<<endl;} private:char _a; }; 问题&#xff1a;类中既可以有成员变量&#xff0c;又可以有成员函数&#xff0c;那么一个类的对象中包含了什么&#xff1f;如何计算一个类的大小&#xff1f; 2…

垃圾填埋气体监测与告警一体化环保监测5G云网关

数字化时代数据采集和传输我认为变得非常重要。为了满足这一需求&#xff0c;我们推出了一款具备多种功能的数据采集器。这款产品不仅集成了8DI干湿节点、4DO继电器、6AI电流/电压型传感器&#xff0c;还支持与多个云平台进行上行对接。通过这些功能&#xff0c;用户可以轻松实…

幻兽帕鲁服务器多少钱?4核16G支持32人在线吗?

4核16G服务器是幻兽帕鲁Palworld推荐的配置&#xff0c;阿里云和腾讯云均推出针对幻兽帕鲁的4核16G服务器&#xff0c;阿里云4核16G幻兽帕鲁专属服务器32元1个月、66元3个月&#xff0c;腾讯云4核16G14M服务器66元1个月、277元3个月、1584元一年。云服务器吧yunfuwuqiba.com分享…

人工智能顶会ICLR 2024热门研究方向大揭秘

图1 由ICLR 2024论文列表生成的词云 ICLR&#xff08;International Conference on Learning Representations&#xff09;自2013年起至今&#xff08;2024年&#xff09;已成功举办12届&#xff0c;被公认为人工智能领域的顶级会议之一。该会议由“深度学习三大巨头”中的 Y…

【深度学习:t-SNE 】T 分布随机邻域嵌入

【深度学习&#xff1a;t-SNE 】T 分布随机邻域嵌入 降低数据维度的目标什么是PCA和t-SNE&#xff0c;两者有什么区别或相似之处&#xff1f;主成分分析&#xff08;PCA&#xff09;t-分布式随机邻域嵌入&#xff08;t-SNE&#xff09; 在 MNIST 数据集上实现 PCA 和 t-SNE结论…

网络基础---初识网络

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、局域网…

$monitor和$strobe都看的是啥

注&#xff1a;本文来自硅芯思见 在编写测试平时&#xff0c;经常会用到$monitor和$strobe监测某些信号&#xff0c;并且使用格式上与$display比较类似&#xff0c;但是它们之间还是存在差异的&#xff0c;它们在当前仿真时间槽&#xff08;time-slot&#xff09;中被执行的区间…

网络安全03---Nginx 解析漏洞复现

目录 一、准备环境 二、实验开始 2.1上传压缩包并解压 2.2进入目录&#xff0c;开始制作镜像 2.3可能会受之前环境影响&#xff0c;删除即可 ​编辑 2.4制作成功结果 2.5我们的环境一个nginx一个php 2.6访问漏洞 2.7漏洞触发结果 2.8上传代码不存在漏洞 2.9补充&#…

中断控制器

1. 中断的理解 1.1 什么是中断 中断: 通常指 某种事件(中断源) 触发了 需要打断CPU , 让CPU暂停当前处理的(保存现场) 任务(usr模式下) 打断(irq异常) 转而去处理 这个事件(在irq模式中) ,事件处理结束后 需要回到(恢复现场) 打断处继续向后执行 1.2 中断控制器的作…

程序员如何应对中年危机

中年危机是一个普遍存在的问题&#xff0c;不仅仅局限于程序员这个职业。不过&#xff0c;对于程序员来说&#xff0c;由于技术更新迅速&#xff0c;中年危机可能更加明显。以下是一些应对中年危机的建议&#xff1a; 持续学习新技术和工具&#xff1a;计算机技术发展迅速&…

特殊类的设计(含单例模式)

文章目录 一、设计一个不能被拷贝的类二、设计一个只能在堆上创建的类三、设计一个只能在栈上创建的类四、设计一个不能被继承的类五、单例模式1.懒汉模式2.饿汉模式 一、设计一个不能被拷贝的类 拷贝只会放生在两个场景中&#xff1a;拷贝构造函数以及赋值运算符重载&#xf…

MySQL介绍、安装和卸载

MySQL介绍、安装和卸载 1. 数据库基本概念2. 数据库类型和常见的关系型数据库2.1 数据库类型2.2 常见的关系型数据库 3. MySQL介绍4. MySQL8的安装和卸载 1. 数据库基本概念 1. 数据 所谓数据&#xff08;Data&#xff09;是指对客观事物进行描述并可以鉴别的符号&#xff0c;…

(四)流程控制ifelse

文章目录 if else用法示例1演示1示例2演示2示例3演示3示例4演示4 逻辑与或非示例1演示1示例2演示2示例3演示3 if elseif else示例1演示1示例2演示2 if else 用法 if(条件表达式成立或为真){ //执行里面 }else{ //否则执行这里面 } 这里:条件表达式成立或为真&#xff0c;数值…

《WebKit 技术内幕》学习之十五(6):Web前端的未来

6 Chromium OS和Chrome的Web应用 6.1 基本原理 HTML5技术已经不仅仅用来编写网页了&#xff0c;也可以用来实现Web应用。传统的操作系统支持本地应用&#xff0c;那么是否可以有专门的操作系统来支持Web应用呢&#xff1f;当然&#xff0c;现在已经有众多基于Web的操作系统&…

环形链表的检测与返回

环形链表 王赫辰/c语言 - Gitee.com 快慢指针的差距可以为除一以外的数吗&#xff1f;不可以如果差奇数则无法发现偶数环&#xff0c;是偶数无法发现奇数环&#xff0c;本题思路为指针相遇则为环&#xff0c;而以上两种情况会稳定差一&#xff0c;导致指针永不相遇 最终返回…