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应该做了一些封装,封装的原理后面再分享出来

相关推荐
xcl09254 小时前
北京24小时自助健身房系统软件开发实战:从架构到部署全流程指南
java·spring boot·架构
一 乐6 小时前
动漫书销售商城|基于springboot + vue动漫书销售商城(源码+数据库+文档)
java·数据库·vue.js·spring boot·毕业设计
卓怡学长6 小时前
w214基于jsp知道特产网
java·intellij-idea
步行cgn6 小时前
Spring 注解使用详解
java·spring
一条小小yu6 小时前
Spring IoC的理解
java·后端·spring
落魄实习生7 小时前
Agent Scope Java 2.x 系列【7】工具使用
java·开发语言·ai
旺仔学长 哈哈7 小时前
springboot钓鱼爱好者交流平台APP设计与实现
java·spring boot·mysql·充电桩管理系统
自强的小白8 小时前
核心功能(Service接口)
java·mybatis
乌暮9 小时前
深入理解 Java 泛型:把「万能盒子」用对、用稳
java·开发语言·后端·学习