加载指定包(加深对Spring框架的理解)

@[TOC]加载指定包的类对象到容器

package com.ruoyi.project.tool.nio;


import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
//import org.apache.ibatis.io.Resources;
//import java.io.FileFilter;
//import java.net.URL;

/**
 *  加载指定包下的类
 *  @author David
 */
public class LoadClassUtils {

    /**
     * 加载指定包
     *
     * @param packagePath
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static void loadSpeckLoad(String packagePath) throws IOException, ClassNotFoundException {
        String filePath = ClassLoader.getSystemResource("com/ruoyi/project").getPath();
        File packageFile = new File(filePath);
        Map<String, Class> map = new HashMap<>();
        loadBean(map, packageFile, packagePath);

        for (Map.Entry<String, Class> entry : map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            System.out.println(key + value);
        }
    }

    /**
     * 递归加载类信息
     *
     * @param map         存放加载对象的容器map
     * @param file        加载的对象文件
     * @param packageName - 文件的包名 例如com.weyao.saas(这个参数是必须要传的,不传的话会导致遍历到目录,class文件不知道在哪个包下)
     * @throws ClassNotFoundException
     */
    public static void loadBean(Map<String, Class> map, File file, String packageName) throws ClassNotFoundException {
        // 目录处理
        if (file.isDirectory()) {
            // 获取目录下的文件对象信息
            File[] files = file.listFiles(new FilenameFilter() {
                // 对文件进行过滤(获取目录及以.class结尾的文件)
                @Override
                public boolean accept(File dir, String name) {
                    if (file.isDirectory() || (file.isFile() && file.getName().endsWith(".class"))) {
                        return true;
                    }
                    return false;
                }
            });

            // 遍历目录下的文件
            for (File subFile : files) {
                // 如果是仍然是目录
                if (subFile.isDirectory()) {
                    // 获取目录名称,例如common、service这种目录名称
                    String subPackageName = subFile.getName();
                    loadBean(map, subFile, packageName + "." + subPackageName);
                } else {
                    // 如果是.class文件
                    loadBean(map, subFile, packageName);
                }
            }
        } else {
            // 判断为文件不再递归直接实例化
            if (file.isFile() && file.getName().endsWith(".class")) {
                String fileName = file.getName();
                System.out.println(fileName);
                System.out.println(fileName.lastIndexOf(".class"));
                String className = fileName.substring(0, fileName.lastIndexOf("."));
                Class<?> aClass = Class.forName(packageName + "." + className);
                map.put(className, aClass);
            }
        }
    }

//    /**
//     * 另一种将包名转化文件对象的方式(但是这个Resources是org.apache.ibatis.io包下的)
//     * 如果有兴趣可以添加Maven依赖玩一下
//     */
//      public  void getPackagePath(String packagePath) throws IOException, ClassNotFoundException {
//            URL resourceURL = Resources.getResourceURL(packagePath.replace(".","/"));
//            String protocol = resourceURL.getProtocol();
//            if("file".equals(protocol)) {
//                String filePath = resourceURL.getFile();
//                File packageFile = new File(filePath);
//                Map<String, Class> map = new HashMap<>();
//                loadBean(map, packageFile, packagePath);
//            }else {
//                TODO 对jar包的解析处理
//            }
//     }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        String packagePath = "com.ruoyi.project";
        loadSpeckLoad(packagePath);
    }

}

小结:三个关键点吧
1 将指定包转换为File或转化为URL再转化为File
2 对层层嵌套的文件,需要采用递归(自己调自己)去处理
3 递归的方法中需要传包名

意义:Spring不就有个扫描指定包的标签吗?例如<context:component-scan base-package="cn.edu.dao"/>。首先通过定义这个指定包,Spring就能帮你把指定包下的定义了@Controller、@Service、@Component,@Repository的类转化为bean对象。然后它就是通过你定义的指定包,然后帮你扫描指定包下的所有.class文件,然后反射得到它的类对象,这样它就掌握了这个类的所有结构信息,当然也包括是否有@Controller、@Service这样的注解,最后Spring框架判断类对象有这种注解,它就会去实例化这个类,然后将实例化的对象加载到容器中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring Framework是一个开源的Java平台,它提供了一组全面的工具来支持Java应用程序开发。它主要括IoC容器、AOP框架、事务管理、MVC框架、DAO框架、连接池等。它可以帮助程序员更好地组织代码,减少重复性工作,提高代码质量。手写Spring框架需要对Java编程和设计模式有较深的了解,并对Spring框架的源码有着深入的研究。 ### 回答2: Spring框架是一个开源的Java平台,用于构建企业级应用程序。它提供了一种全面的编程和配置模型,用于开发基于Java的应用程序和服务。手写Spring框架意味着从头开始实现Spring的核心功能。 手写Spring框架的基本步骤括: 1. 创建一个核心容器,用于管理应用程序中的Bean对象。这个容器需要提供注册、获取和销毁Bean的功能。 2. 定义一个Bean注解,用于标识哪些应该被容器所管理。 3. 创建一个Bean定义,用于存储每个Bean的元数据信息,名、作用域和依赖关系等。 4. 实现依赖注入功能,通过读取Bean定义中的依赖关系,将相关的Bean对象注入到目标Bean中。 5. 提供AOP(面向切面编程)功能,允许开发者在应用程序的特定点进行横切关注点的处理。 6. 实现声明式事务管理功能,使用注解或XML配置方式来处理数据库事务。 7. 提供对不同数据访问技术(如JDBC、ORM框架、NoSQL等)的支持,通过集成相应的库来简化数据访问代码。 8. 增加对Web开发的支持,如处理请求、渲染视图等。 手写Spring框架需要具备对Java语言的深入了解,熟悉反射、代理、设计模式等概念和技术。还需要对依赖注入、AOP、事务管理、Web开发等方面有一定的理解。实现一个完整的Spring框架是一个庞大而复杂的任务,需要经过反复的设计、开发和测试。通过手写Spring框架,可以更深入地理解Spring的原理和内部机制,提高对框架的使用和调试能力。 ### 回答3: 手写Spring框架是一个相当复杂的任务,但我可以简要介绍手写Spring框架的一些关键步骤和组成部分。 1. 依赖注入:Spring框架的核心概念之一是依赖注入。我们需要编写一个容器,负责管理和维护各个对象之间的依赖关系。可以使用反射机制来实现依赖注入。 2. 控制反转:Spring框架通过控制反转(IoC)来管理对象的创建和生命周期。我们需要编写一个BeanFactory,负责加载和实例化对象,并将依赖注入到相应的对象中。 3. 配置文件:手写Spring框架也需要一个配置文件,用于定义对象的依赖关系和属性。我们可以使用XML、注解或者JavaConfig等方式来定义配置文件。 4. AOP支持:Spring框架提供了面向切面编程(AOP)的支持,可以通过编写切面和通知来实现横切关注点的统一处理。我们需要实现一个AOP框架,用于拦截和处理切面逻辑。 5. MVC模式:Spring框架也提供了一个MVC框架,用于处理Web应用程序的请求和响应。我们需要编写一个DispatcherServlet,负责将请求分发给相应的控制器,并处理模型和视图的交互。 6. 整合其他技术:Spring框架还可以与其他技术进行整合,例如数据库访问、事务管理、安全性控制等。我们需要编写相应的模块,将这些技术与Spring框架集成起来。 虽然这只是一个简要的介绍,手写Spring框架是一个非常庞大的工程,需要深入理解Spring的原理和设计思想,并具备扎实的Java编程能力。但通过手写Spring框架,我们可以更好地掌握Spring的核心概念和原理,并加深框架理解
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值