java 获取resource的源码分析续

上一篇博文说明了 java中 class.getResource(String name)  与  classloader.getResource(String name)  中name参数的一些事。

今天来分析下类加载器是怎么加载指定资源的,即classloader.getResource(String name)方法。

先来看下源码:

public URL getResource(String name) {
        URL url;
        if (parent != null) {
            url = parent.getResource(name);
        } else {
            url = getBootstrapResource(name);
        }
        if (url == null) {
            url = findResource(name);
        }
        return url;
    }

当前类加载器(一般是appclassloader)会让父类去加载,父类找不到再通过子类自身findResource(name)方法来找资源,来看下findResource(name)方法的源码,方法定义在appclassloader的父类urlclassloader里面,

 public URL findResource(final String name) {
        /*
         * The same restriction to finding classes applies to resources
         */
        URL url = AccessController.doPrivileged(
            new PrivilegedAction<URL>() {
                public URL run() {
                    return ucp.findResource(name, true);
                }
            }, acc);

        return url != null ? ucp.checkURL(url) : null;
    }

ucp即URLClassPath类,这个类是个关键类,这个类看懂一般就没有问题了,在来看一下URLClassPath里面的findResource(name)方法

 public URL findResource(String name, boolean check) {
        Loader loader;
        for (int i = 0; (loader = getLoader(i)) != null; i++) {
            URL url = loader.findResource(name, check);
            if (url != null) {
                return url;
            }
        }
        return null;
    }

URLClassPath类里面有三个loader类,Loader 本身, jarLoader, fileLoader 三个加载类用于加载不同位置的资源,

Loader 作为父类一般用来加载网络资源,

jarLoader 用来加载jar包内的资源,

fileLoader用来加载本地路径下的资源

每个loader实现不一样,细节自己看源码哦!


现在来看一个现象:

新建一个java 项目, 里面只有一行可以执行代码

public static void main(String[] args) throws Exception {
		
		
		System.out.println(DemoConfig.class.getResource("/WebRoot"));
		
		
	}

将该项目打成一个jar包,然后往里面塞进一个 WebRoot目录, 执行 java -jar ...命令

jar包内目录结构如下:


执行后输出的结果如下:



但是如果你把WebRoot目录放到jar包同层目录,结果又不一样

同层结构如下:


结果如下:



原因大家看了文章应该能理解点

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis是一款优秀的Java持久层框架,它封装了JDBC,使开发者无需关注繁琐的连接、驱动加载等细节,只需关注SQL语句本身。它采用ORM思想解决了实体和数据库映射的问题。MyBatis通过XML或注解配置要执行的SQL语句,并将Java对象和SQL的动态参数进行映射生成最终的SQL语句。最后,MyBatis执行SQL并将结果映射为Java对象返回。 总体执行流程如下: 1. 通过getResourceAsReader(String resource)方法读取mybatis.xml配置文件,生成Reader对象。 2. 使用SqlSessionFactoryBuilder的build()方法,通过构建者模式创建SqlSessionFactory对象。 3. 通过openSession()方法获取DefaultSqlSession对象,用于执行数据库操作。 4. 在进行数据库的insert、update、delete、select等操作后,通过sqlSession.commit()提交事务。 5. 最后使用sqlSession.close()关闭连接,释放资源。 解析mapper节点时,首先获取命名空间并将其放入builderAssistant对象中。然后解析cache-ref、cache、parameterMap、resultMap和Sql片段等内容。接下来是解析增删改查的地方,通过上下文构建statement对象。真正解析增删改查的方法是buildStatementFromContext(list, null)。通过构建者模式生成一个statementParser对象,用于解析增删改查标签。通过parseStatementNode()方法解析和设置各个标签的属性。最后使用构建者模式将解析得到的statement对象添加到builderAssistant对象中,用于构建statement对象。重要的是使用addMappedStatement()方法判断是否为select方法,如果是,则构建一个statement对象并将其添加到MappedStatement类型的statement变量中。最终将statement对象放入configuration对象中,将所有增删改查的标签解析为一个statement对象并放入configuration对象中。 在MyBatis底层源码中,使用了build(Reader reader, String environment, Properties properties)方法来构建SqlSessionFactory对象。实际上,该方法内部调用了build(Reader reader)方法。在build(Reader reader, String environment, Properties properties)方法中,声明了一个XMLConfigBuilder对象parser,通过parser.parse()方法解析XML配置文件,最终返回一个builde对象[3]。 总体来说,MyBatis底层源码分析涉及到读取配置文件、创建SqlSessionFactory对象、解析mapper节点、构建statement对象等过程。这些过程都有各自的细节和步骤,用于实现MyBatis的功能和特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值