Spring是怎么找到resources下面的配置文件的(二)?

前言

Spring是怎么找到resources下面的配置文件的(一)? - 掘金 (juejin.cn) 里面我们探寻了在spring中,ClassPathResource封装了我们classpath类资源,然后容器BeanFactory通过通过java类加载机制在java.class.path路径中的资源。

Java.class.path是系统属性的一个key,通过System.getProperty("java.class.path"),类加载器就能获取加载类的路径。

这里我们探寻一下System.getProperty("java.class.path")获取到的系统属性是怎么来的或者说是怎么进行赋值的呢?

我们说一下结论: Java.class.path这个系统属性是我们运行程序的时候,也就是java.exe -classpath时候指定的,指定的classpath就是两类,一个就是我们项目compile编译生成的target/classes目录,另一个就是我们项目pom包里面的依赖,也就是lib。

我都是用的idea开发maven项目,直接点击执行的时候,在console中会有项目启动的指令!由于现在idea的便捷,我往往都忽略了这里面的参数

探究原理

首先我们了解一下什么是classpath和java.class.path

什么是classpath 与 java.class.path?

启动 java 程序时,会根据 classpath 拼接 java.class.path 。 Java.class.path是由classpath拼接来的

在IDE中运行Java程序,IDE自动传入的-classpath参数是当前工程的bin目录和引入的jar包。 而classpath有两种设置方式,一种是在系统环境变量中设计classpath环境变量,不推荐,因为会污染整个系统环境;另一种是在启动jvm时设置classpath变量。

在idea中运行java程序,会自动传入的-classpath参数是当前工程的bin目录和引入的jar包

Idea中的classpath呢?

很好理解,classpath就是我们编写的java类文件编译后生成的字节码class文件目录,

我们打开项目结构,可以看到默认就是我们的老朋友*\target\classes,而且支持自定义!

那些文件会被编译进*\target\classes中呢?

我们打开项目结构->modules->Sources,右边列出了4个项目中的文件类型:

Source Folders:表示的都是代码源文件目录,生成的class文件会输出到target->classess文件夹中,但是里面的源文件不会复制到target->classes文件夹中

Test Source Folders: 表示的都是测试代码源文件目录,生成的class文件同样会输出到target->classess文件夹中,并且里面的源文件不会复制到target->classes文件夹中

Resource Folders: 表示的都是资源文件目录,这些目录里面的文件会在代码编译运行被直接复制到target->classess文件夹中

Excluded Folders:表示的是target文件夹生成的位置,target是IDEA编译后的一些class信息存放地,里面有子目录target->classes来存储编译后的字节码。

target->classes即为classpath路径位置,任何我们需要在classpath:前缀中获取的资源都必须在target->classes文件夹中找到,否则将出现java.io.FileNotFoundException的错误信息。

扩展

Jar包目录结构

maven install,将项目打包成jar包,包含所有三方依赖的jar。它与传统jar包最大的不同是包含了一个lib目录和内嵌了web容器。 可以看到jar包下就有只有三个目录:BOOT-INF,META-INF,ORG

该目录比使用传统jar命令打包结构更复杂一些,目录含义如下:

  • BOOT-INF/classes:目录存放应用编译后的class文件。
  • BOOT-INF/lib:目录存放应用依赖的第三方JAR包文件。
  • META-INF:目录存放应用打包信息(Maven坐标、pom文件)和MANIFEST.MF文件。
  • org:目录存放SpringBoot相关class文件。

点开BOOT-INF,可以发现,我们编译输出在target的classe文件全在这里,并且这里还有我们依赖的lib

Maven编译生成的jar包

普通的jar包

普通的jar包只包含工程源码编译出的class文件以及资源文件,而不包含任何依赖;同时还包括pom文件,说明该包的依赖信息; 在工程pom文件下这样写,可生成普通的jar包:

java 复制代码
<packaging>jar<packaging>

或者,不写,因为packaging默认打包类型为jar

包含所有依赖的jar包

普通的jar包,只在pom文件中包含依赖信息,而不包含真正的依赖,但同时maven也可以打包生成包含所有依赖的jar文件

maven打包生成的普通jar包,只包含该工程下源码编译结果,不包含依赖内容。同时,maven提供以下方式生成包含所有依赖的jar文件,依赖以class的方式存在;

  1. 将此plugin添加到pom文件中
java 复制代码
             <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <!--这部分可有可无,加上的话则直接生成可运行jar包-->
                    <!--<archive>-->
                        <!--<manifest>-->
                            <!--<mainClass>${exec.mainClass}</mainClass>-->
                        <!--</manifest>-->
                    <!--</archive>-->
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
            </plugin>

如果出现CLASS重名的情况,这时候就要把最新的版本号添加进去即可,

2.在当前项目下执行mvn assembly:assembly, 执行成功后会在target文件夹下多出一个以-jar-with-dependencies结尾的JAR包. 这个JAR包就包含了项目所依赖的所有JAR的CLASS.

3.如果不希望依赖的JAR包变成CLASS的话,可以修改ASSEMBLY插件.

找到assembly在本地的地址,一般是 c:/users/${your_login_name}/.m2/\org\apache\maven\plugins\maven-assembly-plugin\2.4 用WINZIP或解压工具打开此目录下的maven-assembly-plugin-2.4.jar, 找到assemblies\jar-with-dependencies.xml 把里面的UNPACK改成FALSE即可

可运行jar包

maven默认打包生成的jar是不能够直接运行的,因为在jar文件的META-INF/MANIFEST.MF文中没有Main-Class一行,为了生成可执行的jar文件,需要借助maven的插件,maven-shade-plugin,配置该插件如下:

xml 复制代码
 <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.3</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>${exec.mainClass}</mainClass>
                                </transformer>
                            </transformers>
                            <artifactSet>
                            </artifactSet>
                            <!--<outputFile>${project.build.directory}/${project.artifactId}-${project.version}-fat.jar</outputFile>-->
                        </configuration>
                    </execution>
                </executions>
            </plugin>

但是我的项目打包的时候只用了如下的配置:

xml 复制代码
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <addResources>true</addResources>
            </configuration>
        </plugin>
    </plugins>
</build>

可以看到,springboot应该做了一些封装,封装的原理后面再分享出来

相关推荐
神仙别闹11 分钟前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭35 分钟前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫1 小时前
泛型(2)
java
超爱吃士力架1 小时前
邀请逻辑
java·linux·后端
南宫生1 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石1 小时前
12/21java基础
java
李小白661 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp1 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶2 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
n北斗2 小时前
常用类晨考day15
java