精华内容
下载资源
问答
  • 2021-07-25 10:47:47

    最近工作当中遇到过好几例,由于项目当中依赖了一些框架,而这些框架无法直接修改时,我就直接本地代码写了一个同名同包路径的类,可以直接覆盖框架的类(本文说的框架类,不包括jdk的),屡试不爽。但是心里不免有疑问,为啥我本地写的同名同路径的类,可以覆盖三方框架的类呢?如果我依赖了jarA和jarB,俩jar包有一个同名同路径的类,那JVM会加载哪一个类呢?听同事说过,他们之前遇到过一同名同路径的类问题,测试环境和生产环境加载jar包的顺序不一样,导致出现线上事故。有这些疑问,心里也比较慌,所以特意花了些时间研究了下。

    谁控制jar包的加载顺序的?

    查了很多资料,比较靠谱的说法是,操作系统本身,控制了jar包的默认加载顺序。

    而jar包的加载顺序,是跟classpath这个参数有关,当使用idea启动springboot的服务时,可以看到classpath参数的:

    -classpath "/Users/luoxiaohui/Develop/codeyun/java_advanced/eureka-feign-demo/eureka-feign/target/classes:/Users/luoxiaohui/.m2/repository/org/springframework/cloud/spring-cloud-starter-netflix-eureka-server/2.1.0.RELEASE/spring-cloud-starter-netflix-eureka-server-2.1.0.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/cloud/spring-cloud-starter/2.1.0.RELEASE/spring-cloud-starter-2.1.0.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/cloud/spring-cloud-context/2.1.0.RELEASE/spring-cloud-context-2.1.0.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/security/spring-security-crypto/5.1.6.RELEASE/spring-security-crypto-5.1.6.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/cloud/spring-cloud-commons/2.1.0.RELEASE/spring-cloud-commons-2.1.0.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/security/spring-security-rsa/1.0.7.RELEASE/spring-security-rsa-1.0.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/bouncycastle/bcpkix-jdk15on/1.60/bcpkix-jdk15on-1.60.jar:/Users/luoxiaohui/.m2/repository/org/bouncycastle/bcprov-jdk15on/1.60/bcprov-jdk15on-1.60.jar:/Users/luoxiaohui/.m2/repository/org/springframework/cloud/spring-cloud-netflix-eureka-server/2.1.0.RELEASE/spring-cloud-netflix-eureka-server-2.1.0.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/boot/spring-boot-starter-web/2.1.7.RELEASE/spring-boot-starter-web-2.1.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/boot/spring-boot-starter-json/2.1.7.RELEASE/spring-boot-starter-json-2.1.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.9.9/jackson-datatype-jdk8-2.9.9.jar:/Users/luoxiaohui/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.9.9/jackson-datatype-jsr310-2.9.9.jar:/Users/luoxiaohui/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.9.9/jackson-module-parameter-names-2.9.9.jar:/Users/luoxiaohui/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/2.1.7.RELEASE/spring-boot-starter-tomcat-2.1.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.22/tomcat-embed-core-9.0.22.jar:/Users/luoxiaohui/.m2/repository/org/apache/tomcat/embed/tomcat-embed-el/9.0.22/tomcat-embed-el-9.0.22.jar:/Users/luoxiaohui/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.22/tomcat-embed-websocket-9.0.22.jar:/Users/luoxiaohui/.m2/repository/org/hibernate/validator/hibernate-validator/6.0.17.Final/hibernate-validator-6.0.17.Final.jar:/Users/luoxiaohui/.m2/repository/javax/validation/validation-api/2.0.1.Final/validation-api-2.0.1.Final.jar:/Users/luoxiaohui/.m2/repository/org/jboss/logging/jboss-logging/3.3.2.Final/jboss-logging-3.3.2.Final.jar:/Users/luoxiaohui/.m2/repository/com/fasterxml/classmate/1.4.0/classmate-1.4.0.jar:/Users/luoxiaohui/.m2/repository/org/springframework/spring-web/5.1.9.RELEASE/spring-web-5.1.9.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/spring-beans/5.1.9.RELEASE/spring-beans-5.1.9.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/spring-webmvc/5.1.9.RELEASE/spring-webmvc-5.1.9.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/spring-aop/5.1.9.RELEASE/spring-aop-5.1.9.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/spring-expression/5.1.9.RELEASE/spring-expression-5.1.9.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/boot/spring-boot-starter-actuator/2.1.7.RELEASE/spring-boot-starter-actuator-2.1.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/boot/spring-boot-actuator-autoconfigure/2.1.7.RELEASE/spring-boot-actuator-autoconfigure-2.1.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/boot/spring-boot-actuator/2.1.7.RELEASE/spring-boot-actuator-2.1.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/io/micrometer/micrometer-core/1.1.5/micrometer-core-1.1.5.jar:/Users/luoxiaohui/.m2/repository/org/hdrhistogram/HdrHistogram/2.1.9/HdrHistogram-2.1.9.jar:/Users/luoxiaohui/.m2/repository/org/latencyutils/LatencyUtils/2.0.3/LatencyUtils-2.0.3.jar:/Users/luoxiaohui/.m2/repository/org/springframework/boot/spring-boot-starter-freemarker/2.1.7.RELEASE/spring-boot-starter-freemarker-2.1.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/freemarker/freemarker/2.3.28/freemarker-2.3.28.jar:/Users/luoxiaohui/.m2/repository/org/springframework/spring-context-support/5.1.9.RELEASE/spring-context-support-5.1.9.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/cloud/spring-cloud-netflix-hystrix/2.1.0.RELEASE/spring-cloud-netflix-hystrix-2.1.0.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/boot/spring-boot-starter-aop/2.1.7.RELEASE/spring-boot-starter-aop-2.1.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/aspectj/aspectjweaver/1.9.4/aspectjweaver-1.9.4.jar:/Users/luoxiaohui/.m2/repository/org/springframework/cloud/spring-cloud-netflix-eureka-client/2.1.0.RELEASE/spring-cloud-netflix-eureka-client-2.1.0.RELEASE.jar:/Users/luoxiaohui/.m2/repository/com/netflix/eureka/eureka-client/1.9.8/eureka-client-1.9.8.jar:/Users/luoxiaohui/.m2/repository/org/codehaus/jettison/jettison/1.3.7/jettison-1.3.7.jar:/Users/luoxiaohui/.m2/repository/stax/stax-api/1.0.1/stax-api-1.0.1.jar:/Users/luoxiaohui/.m2/repository/com/netflix/netflix-commons/netflix-eventbus/0.3.0/netflix-eventbus-0.3.0.jar:/Users/luoxiaohui/.m2/repository/com/netflix/netflix-commons/netflix-infix/0.3.0/netflix-infix-0.3.0.jar:/Users/luoxiaohui/.m2/repository/commons-jxpath/commons-jxpath/1.3/commons-jxpath-1.3.jar:/Users/luoxiaohui/.m2/repository/joda-time/joda-time/2.10.3/joda-time-2.10.3.jar:/Users/luoxiaohui/.m2/repository/org/antlr/antlr-runtime/3.4/antlr-runtime-3.4.jar:/Users/luoxiaohui/.m2/repository/org/antlr/stringtemplate/3.2.1/stringtemplate-3.2.1.jar:/Users/luoxiaohui/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar:/Users/luoxiaohui/.m2/repository/com/google/code/gson/gson/2.8.5/gson-2.8.5.jar:/Users/luoxiaohui/.m2/repository/org/apache/commons/commons-math/2.2/commons-math-2.2.jar:/Users/luoxiaohui/.m2/repository/javax/ws/rs/jsr311-api/1.1.1/jsr311-api-1.1.1.jar:/Users/luoxiaohui/.m2/repository/com/netflix/servo/servo-core/0.12.21/servo-core-0.12.21.jar:/Users/luoxiaohui/.m2/repository/com/sun/jersey/jersey-core/1.19.1/jersey-core-1.19.1.jar:/Users/luoxiaohui/.m2/repository/com/sun/jersey/jersey-client/1.19.1/jersey-client-1.19.1.jar:/Users/luoxiaohui/.m2/repository/com/sun/jersey/contribs/jersey-apache-client4/1.19.1/jersey-apache-client4-1.19.1.jar:/Users/luoxiaohui/.m2/repository/org/apache/httpcomponents/httpclient/4.5.9/httpclient-4.5.9.jar:/Users/luoxiaohui/.m2/repository/org/apache/httpcomponents/httpcore/4.4.11/httpcore-4.4.11.jar:/Users/luoxiaohui/.m2/repository/commons-codec/commons-codec/1.11/commons-codec-1.11.jar:/Users/luoxiaohui/.m2/repository/com/google/inject/guice/4.1.0/guice-4.1.0.jar:/Users/luoxiaohui/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:/Users/luoxiaohui/.m2/repository/com/github/vlsi/compactmap/compactmap/1.2.1/compactmap-1.2.1.jar:/Users/luoxiaohui/.m2/repository/com/github/andrewoma/dexx/dexx-collections/0.2/dexx-collections-0.2.jar:/Users/luoxiaohui/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.9.0/jackson-annotations-2.9.0.jar:/Users/luoxiaohui/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.9.9/jackson-core-2.9.9.jar:/Users/luoxiaohui/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.9.9/jackson-databind-2.9.9.jar:/Users/luoxiaohui/.m2/repository/com/sun/jersey/jersey-servlet/1.19.1/jersey-servlet-1.19.1.jar:/Users/luoxiaohui/.m2/repository/com/sun/jersey/jersey-server/1.19.1/jersey-server-1.19.1.jar:/Users/luoxiaohui/.m2/repository/com/netflix/eureka/eureka-core/1.9.8/eureka-core-1.9.8.jar:/Users/luoxiaohui/.m2/repository/org/codehaus/woodstox/woodstox-core-asl/4.4.1/woodstox-core-asl-4.4.1.jar:/Users/luoxiaohui/.m2/repository/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2.jar:/Users/luoxiaohui/.m2/repository/com/netflix/archaius/archaius-core/0.7.6/archaius-core-0.7.6.jar:/Users/luoxiaohui/.m2/repository/com/google/code/findbugs/jsr305/3.0.1/jsr305-3.0.1.jar:/Users/luoxiaohui/.m2/repository/com/google/guava/guava/16.0/guava-16.0.jar:/Users/luoxiaohui/.m2/repository/javax/inject/javax.inject/1/javax.inject-1.jar:/Users/luoxiaohui/.m2/repository/com/fasterxml/jackson/dataformat/jackson-dataformat-xml/2.9.9/jackson-dataformat-xml-2.9.9.jar:/Users/luoxiaohui/.m2/repository/com/fasterxml/jackson/module/jackson-module-jaxb-annotations/2.9.9/jackson-module-jaxb-annotations-2.9.9.jar:/Users/luoxiaohui/.m2/repository/org/codehaus/woodstox/stax2-api/3.1.4/stax2-api-3.1.4.jar:/Users/luoxiaohui/.m2/repository/com/fasterxml/woodstox/woodstox-core/5.0.3/woodstox-core-5.0.3.jar:/Users/luoxiaohui/.m2/repository/com/thoughtworks/xstream/xstream/1.4.10/xstream-1.4.10.jar:/Users/luoxiaohui/.m2/repository/xmlpull/xmlpull/1.1.3.1/xmlpull-1.1.3.1.jar:/Users/luoxiaohui/.m2/repository/xpp3/xpp3_min/1.1.4c/xpp3_min-1.1.4c.jar:/Users/luoxiaohui/.m2/repository/org/springframework/cloud/spring-cloud-starter-netflix-archaius/2.1.0.RELEASE/spring-cloud-starter-netflix-archaius-2.1.0.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/cloud/spring-cloud-netflix-ribbon/2.1.0.RELEASE/spring-cloud-netflix-ribbon-2.1.0.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/cloud/spring-cloud-netflix-archaius/2.1.0.RELEASE/spring-cloud-netflix-archaius-2.1.0.RELEASE.jar:/Users/luoxiaohui/.m2/repository/commons-configuration/commons-configuration/1.8/commons-configuration-1.8.jar:/Users/luoxiaohui/.m2/repository/commons-lang/commons-lang/2.6/commons-lang-2.6.jar:/Users/luoxiaohui/.m2/repository/org/springframework/cloud/spring-cloud-starter-netflix-ribbon/2.1.0.RELEASE/spring-cloud-starter-netflix-ribbon-2.1.0.RELEASE.jar:/Users/luoxiaohui/.m2/repository/com/netflix/ribbon/ribbon/2.3.0/ribbon-2.3.0.jar:/Users/luoxiaohui/.m2/repository/com/netflix/ribbon/ribbon-transport/2.3.0/ribbon-transport-2.3.0.jar:/Users/luoxiaohui/.m2/repository/io/reactivex/rxnetty-contexts/0.4.9/rxnetty-contexts-0.4.9.jar:/Users/luoxiaohui/.m2/repository/io/reactivex/rxnetty-servo/0.4.9/rxnetty-servo-0.4.9.jar:/Users/luoxiaohui/.m2/repository/com/netflix/hystrix/hystrix-core/1.5.18/hystrix-core-1.5.18.jar:/Users/luoxiaohui/.m2/repository/io/reactivex/rxnetty/0.4.9/rxnetty-0.4.9.jar:/Users/luoxiaohui/.m2/repository/com/netflix/ribbon/ribbon-core/2.3.0/ribbon-core-2.3.0.jar:/Users/luoxiaohui/.m2/repository/com/netflix/ribbon/ribbon-httpclient/2.3.0/ribbon-httpclient-2.3.0.jar:/Users/luoxiaohui/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar:/Users/luoxiaohui/.m2/repository/com/netflix/netflix-commons/netflix-commons-util/0.3.0/netflix-commons-util-0.3.0.jar:/Users/luoxiaohui/.m2/repository/com/netflix/ribbon/ribbon-loadbalancer/2.3.0/ribbon-loadbalancer-2.3.0.jar:/Users/luoxiaohui/.m2/repository/com/netflix/netflix-commons/netflix-statistics/0.1.1/netflix-statistics-0.1.1.jar:/Users/luoxiaohui/.m2/repository/io/reactivex/rxjava/1.3.8/rxjava-1.3.8.jar:/Users/luoxiaohui/.m2/repository/com/netflix/ribbon/ribbon-eureka/2.3.0/ribbon-eureka-2.3.0.jar:/Users/luoxiaohui/.m2/repository/org/slf4j/slf4j-api/1.7.26/slf4j-api-1.7.26.jar:/Users/luoxiaohui/.m2/repository/org/springframework/boot/spring-boot-starter/2.1.7.RELEASE/spring-boot-starter-2.1.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/boot/spring-boot/2.1.7.RELEASE/spring-boot-2.1.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/spring-context/5.1.9.RELEASE/spring-context-5.1.9.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.1.7.RELEASE/spring-boot-autoconfigure-2.1.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.1.7.RELEASE/spring-boot-starter-logging-2.1.7.RELEASE.jar:/Users/luoxiaohui/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/Users/luoxiaohui/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/Users/luoxiaohui/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.11.2/log4j-to-slf4j-2.11.2.jar:/Users/luoxiaohui/.m2/repository/org/apache/logging/log4j/log4j-api/2.11.2/log4j-api-2.11.2.jar:/Users/luoxiaohui/.m2/repository/org/slf4j/jul-to-slf4j/1.7.26/jul-to-slf4j-1.7.26.jar:/Users/luoxiaohui/.m2/repository/javax/annotation/javax.annotation-api/1.3.2/javax.annotation-api-1.3.2.jar:/Users/luoxiaohui/.m2/repository/org/yaml/snakeyaml/1.23/snakeyaml-1.23.jar:/Users/luoxiaohui/.m2/repository/org/springframework/spring-core/5.1.9.RELEASE/spring-core-5.1.9.RELEASE.jar:/Users/luoxiaohui/.m2/repository/org/springframework/spring-jcl/5.1.9.RELEASE/spring-jcl-5.1.9.RELEASE.jar:/Users/luoxiaohui/.m2/repository/javax/xml/bind/jaxb-api/2.3.1/jaxb-api-2.3.1.jar:/Users/luoxiaohui/.m2/repository/javax/activation/javax.activation-api/1.2.0/javax.activation-api-1.2.0.jar:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar"
    

    包路径越靠前,越先被加载。换句话说,如果靠前的jar包里的类被加载了,后面jar包里有同名同路径的类,就会被忽略掉,不会被加载。

    而且,使用idea启动服务时,可以通过idea直接修改classpath
    在这里插入图片描述
    如果我们将<module source>(也就是我们自己写的类)拖到最下面,可以发现,我们本地写的跟三方框架同名同路径的类,并不会被加载,也不会覆盖三方框架的类。

    我们如何控制jar包的加载顺序?

    由于jar包的默认加载顺序,是操作系统本身控制的,但是我们可以通过修改classpath,从而来调整jar包加载顺序。

    参考资料

    https://www.cnblogs.com/saaav/p/7716179.html
    https://docs.oracle.com/javase/8/docs/technotes/tools/findingclasses.html#jarclass
    https://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html

    更多相关内容
  • 主要介绍了详解Spring Boot 配置加载顺序及属性加载顺序,本章内容基于 Spring Boot 2.0 进行详解,感兴趣的朋友跟随脚本之家小编一起看看吧
  • 今天我们旧事重提,再来谈谈css的加载,及加载顺序。 通常的css加载顺序 一般情况下,我们css样式表是放在头部,同时为了减少请求,我们通常对css进行一个合并压缩。 目前我们css一般是如下加载的: <head> ...
  • Java中类的加载顺序

    2021-01-21 17:09:58
    不过我们可以换个直接的问法,如果类A和类B中有静态变量,静态语句块,非静态变量,非静态语句块,构造函数,静态方法,非静态方法,同时类A继承类B,请问当实例化A时,类内部的加载顺序是什么?  当时我也是一头...
  • spring加载顺序讨论

    2019-12-09 14:22:15
    加载顺序讨论加载顺序讨论
  • 主要介绍了springboot配置文件的加载顺序解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 主要介绍了如何正确控制springboot中bean的加载顺序总结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
  • 主要给大家介绍了关于tomcat8改了jar加载顺序的踩坑记录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
  • 主要介绍了SpringBoot内部外部配置文件加载顺序解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 主要介绍了Java中类的加载顺序剖析(常用于面试题),本文直接给出代码实例和运行结果,给后给出了加载过程总结,需要的朋友可以参考下
  • 查找一些教材中(w3schools等),只说css的顺序是“元素上的style” > “文件头上的style元素” >“外部样式文件”,但对于样式文件中的多个相同样式的优先级怎样排列,没有详细说明。经过测试和继续搜索,得知...
  • 本篇文章是对Java中父类与子类的加载顺序进行了详细的分析介绍,需要的朋友参考下
  • 主要介绍了java 代码块与静态代码块加载顺序的相关资料,需要的朋友可以参考下
  • 本篇文章主要介绍了Vue的加载顺序探讨,详细的介绍了加载顺序以及如何判断所有的子组件加载完成。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 本篇文章主要是对jsp页面中的代码执行加载顺序进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助
  • 页面加载顺序为:先加载head标签中link中的css,而我把所有的图标都写在了css中,导致图标出来了,body中的内容却还没加载完,所以采用loading的方法,适应我们打开页面时的习惯。
  • 主要介绍了Java代码块与代码加载顺序原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • Spring Bean 加载顺序 .

    2016-10-13 16:18:50
    Spring Bean 加载顺序 实验小例子
  • 主要介绍了Django框架模板文件使用及模板文件加载顺序,结合实例形式分析了Django框架模板文件的功能、用法及加载顺序,需要的朋友可以参考下
  • DOM文档的加载顺序是由上而下的顺序加载; 1、DOM加载到link标签 css文件的加载是与DOM的加载并行的,也就是说,css在加载时Dom还在继续加载构建,而过程中遇到的css样式或者img,则会向服务器发送一个请求,待资源...
  • style和class的加载顺序到底谁先谁后,谁又会覆盖谁,在接下来的示例中将为大家详细介绍下,希望对大家有所帮助
  • 主要介绍了举例说明Java中代码块的执行顺序,需要的朋友可以参考下
  • 有的php扩展,加载是有先后顺序的,如果搞错了,会导致扩展无法加载。 1,pdo_sqlsrv是sqlserver扩展,如果在pdo扩展之前加载就会报以下错误 PHP Warning: PHP Startup: Unable to load dynamic library ‘pdo_...
  • web.xmllistener、filter、servlet加载顺序.pdf
  • 主要介绍了web.xml中servlet, bean, filter, listenr 加载顺序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 极大方便的开发效率,基于这样的场景,产生了一些关于配置文件加载顺序的一系列问题,在此进行记录和学习。 2.配置文件的加载顺序 其实关于SpringBoot配置文件加载顺序的文章有很多,这里就不详细...

    1.背景

            之前对于公司统一架构的组件在安装后,有些配置项不会使用classpath下面的application.properties中的值,而是去相应组件的config/config.properties去加载,这样的好处是,本地搭建的测试环境和线程环境对于配置文件是不冲突的,极大方便的开发效率,基于这样的场景,产生了一些关于配置文件加载顺序的一系列问题,在此进行记录和学习。

    2.配置文件的加载顺序

            其实关于SpringBoot配置文件加载顺序的文章有很多,这里就不详细说明了,贴出两篇大佬总结的文章:

                    SpringBoot 配置文件位置的加载顺序

                  【小家Spring】一篇文章彻底搞懂Spring Boot配置文件的加载顺序(项目内部配置和外部配置)

            整体的加载顺序如下图:

    在这里插入图片描述

              在项目路径下面配置文件的加载顺序

    在这里插入图片描述

    3.深入理解

           在Spring项目中,每一个配置文件被加载后,都会对应一个JVM中的实例对象,这个实例对象会被Spring容器所管理,以上图举例config/application.properties、application.properties、classpath:application.properties、classpath:config/application.properties,都有对应的实例对象表示这个配置文件。

           所以说这些配置文件都会被Spring容器所管理,具体哪一个生效就要看前面的加载顺序了,如果我们指定了具体哪一个配置文件生效,那么他的优先级是比较高的,其他的会排在他后面生效。

           Spring会使用Environment接口的实现类管理所有的配置文件的对象,这个Environment在Spring中也是一个很重要的概念,如果你阅读Spring、SpringBoot的源码会发现,会有一步是初始化并配置Environment的代码,也就是在这里完成了对于配置文件的解析,即将配置文件对应成Java的对象,并交给Spring进行管理。

           那么此时的重点,就应该去分析在从Environment中获取配置项的value时,是获取哪一个配置文件中值就可以了,跟着environment.getProperty进行查看:

           1.实现EnvironmentAware接口,将setEnvironment方法将在Spring容器启动过程中,自动调用,然后查看environment.getProperty("component.id")的调用流程

            2.查看getProperty方法,会进入PropertyResolver接口中,因为Environment继承了PropertyResolver接口

            3.PropertyResolver接口中的String getProperty(String key),只有PropertySourcesPropertyResolver进行了实现,那么我们只需要查看相应的方法即可。

            org.springframework.core.env.PropertySourcesPropertyResolver类的getProperty方法

    @Override
    @Nullable
    public String getProperty(String key) {
    	return getProperty(key, String.class, true);
    }
    
    @Nullable
    protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
    	if (this.propertySources != null) {
    		//1.获取到所有的配置资源,也就是配置对象列表
    		for (PropertySource<?> propertySource : this.propertySources) {
    			//2.从配置对象中获取配置项value
    			Object value = propertySource.getProperty(key);
    			//3. 如果value为空,则进行遍历下一个配置对象
    			//   如果value不为空,则进行处理,然后直接返回当前配置对象的值,不再继续遍历
    			if (value != null) {
    
    				//3.1 解析嵌套占位符,用于解析是否用占位符,并且进行转换
    				if (resolveNestedPlaceholders && value instanceof String) {
    					value = resolveNestedPlaceholders((String) value);
    				}
    				logKeyFound(key, propertySource, value);
    
    				//3.2 如果有必要,则进行类型转换,然后进行返回
    				return convertValueIfNecessary(value, targetValueType);
    			}
    		}
    	}
    
    	return null;
    }

            到此步我们发现,environment.getProperty("component.id")就是依次遍历所有的配置对象,如果能从这个配置对象中获取到值,那么就进行一些解析和转换后,直接进行返回了。这样的话,猜测一下也知道,肯定是this.propertySources是按照一定规则排序的,才能实现SpringBoot配置文件加载的顺序性。他的顺序性一定也是按照config/application.properties、application.properties、classpath:application.properties、classpath:config/application.properties中的顺序进行的。

             有上图和代码进行分析,我们知道如果在config/application.properties、application.properties、classpath:application.properties、classpath:config/application.properties中有配置项是重复的,那么就会找到配置对象的先后顺序进行生效和查找,只要其中一个配置对象不为空,则直接返回了。

             如果我们指定其中一个文件生效的,那么他的顺序是怎么样的呢?假设我们指定application-dev1.properties文件生效

            总结:

           1.所有的配置文件都会有对应的配置对象与之关联,并且会放到一个集合中进行管理

           2.默认情况下,如果有多个配置文件的配置项是重复的,那么就会按照SpringBoot的配置文件的加载顺序进行生效,不是说这些配置文件只有一个有用,其他的配置文件中的配置项是无用的,他们都是会生效的,只是在有配置项重复时,谁的优先级高用谁的。

     

    4.自定义加载顺序

            其关键就是修改this.propertySources中配置对象的顺序,这样就可以实现他的顺序了,或者说我们想要让我们自定义目录的优先级最高,此时也只需要将这个配置对象加到集合的头部就行,关于获取这个propertySources对象可以实现ConfigurableEnvironment这个接口就行,ConfigurableEnvironment是Environment的子接口,一般我们实现EnvironmentAware接口,传递过来的也是ConfigurableEnvironment的实现类,所有我们可以将Environment强转为ConfigurableEnvironment然后进行设置。

           如下是实现的例子:

    public class LoadConfigBeanFactoryPostProcessor implements BeanFactoryPostProcessor, EnvironmentAware, Ordered {
    
        private static final Logger logger = LoggerFactory.getLogger(com.xxx.ocdvs.common.config.LoadConfigBeanFactoryPostProcessor.class);
    
        private static final String CONFIG_PROPERTIES = "config.properties";
    
        private ConfigurableEnvironment environment;
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            String configPath = getConfigPropertiesPath();
            logger.info("- Config path is {}.", configPath);
            Properties properties = new Properties();
            try {
                properties.load(new FileInputStream(configPath));
            } catch (IOException e) {
                logger.info("- Fail to load config properties because the path is error.");
            }
            environment.getPropertySources().addFirst(new PropertiesPropertySource(CONFIG_PROPERTIES, properties));
        }
    
        @Override
        public void setEnvironment(Environment environment) {
            this.environment = (ConfigurableEnvironment) environment;
        }
    
        @Override
        public int getOrder() {
            return -1;
        }
    
    
        /**
         * 拿到config.properties文件的目录
         */
        public String getConfigPropertiesPath(){
            return getConfPropertiesPath(CONFIG_PROPERTIES);
        }
    
        /**
         * 拿到/conf下properties路径,例如拿到config.properties的路径
         * @param file /conf文件夹下的.properties文件
         */
        protected String getConfPropertiesPath(String file){
            //这个路径只是举例,可以是你想指定的任何路径,我们统一架构是先安装组件,然后会根据动态的生成服务器、数据库、注册中心的地址
            //使用一个配置文件进行保存,这个文件的地址不是在tomcat目录下面
            String propertiesPath = "/config/"+file;
            return propertiesPath;
        }
    }
    

            关键点:

            1.需要在Spring Bean生命周期实例化之前的阶段执行,也就是需要在BeanFactoryPostProcessor接口的postProcessBeanFactory方法中进行实现,关于Spring的扩展点你可能知道几个,但是对于此步骤不能在BeanPostProcessor生效之前使用。具体原因还是要自定义的加载顺序要优于Spring Bean生命周期之前,因为在Spring Bean生命周期中,会进行属性赋值,此时会从environment中获取值。

            2.将Environment强转为ConfigurableEnvironment,这样才能调用ConfigurableEnvironment.getPropertySources()获取配置对象集合进行处理。

            3.实现Ordered接口,其实不实现也行,但是实现了Ordered 接口,以后如果有两个自定义的路径,你先指定谁的优先级高,可以使用Ordered接口轻松实现。

    展开全文
  • 该项目展示spring配置文件的那些bean的加载顺序
  • springboot中bean的加载顺序

    千次阅读 2022-02-24 17:20:44
    1、为什么要控制spring的加载顺序 当你在项目启动时需要提前做一个业务的初始化工作时,或者你正在开发某个中间件需要完成自动装配时。你会声明自己的Configuration类,但是可能你面对的是好几个有互相依赖的Bean。...

    springboot中bean的加载顺序

    一、为什么要控制

    当你在项目启动时需要提前做一个业务的初始化工作时,或者你正在开发某个中间件需要完成自动装配时。你会声明自己的Configuration类,但是可能你面对的是好几个有互相依赖的Bean。如果不加以控制,这时候可能会报找不到依赖的错误,这个时候需要通过一些手段来控制springboot中的bean加载顺序。

    二、怎么控制

    @DependsOn

    @DependsOn注解可以用来控制bean的创建顺序,该注解用于声明当前bean依赖于另外一个bean。所依赖的bean会被容器确保在当前bean实例化之前被实例化。与@Component或@Bean配合使用
    demo

    @Slf4j
    @Configuration
    @ConfigurationProperties(prefix = "dict")
    public class SpringConfig {
        @Component(value = "EventSource")
        public class EventSource {
            public EventSource(){
                System.out.println("事件源创建");
            }
        }
        /**
         * 监听类
         */
        @Component
        @DependsOn(value = {"EventSource"})
        public class EventTListener {
    
            public EventTListener(){
                System.out.println("监听器创建");
            }
        }
    }
    
    

    在这里插入图片描述

    参数注入

    package com.sinosoft.springbootplus.test.config;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.DependsOn;
    import org.springframework.stereotype.Component;
    
    /**
     * @author lsh
     * @date 2022/2/25
     */
    @Slf4j
    @Configuration
    @ConfigurationProperties(prefix = "dict")
    public class SpringConfig {
        @Component
        public class Event{
            public Event(){
                System.out.println("事件事件");
            }
        }
        
        @Component
        public class EventSource{
            public EventSource(Event e){
                System.out.println("事件源创建");
            }
        }
    
    
        @Component
        public class EventTListener {
    
            public EventTListener(){
                System.out.println("监听器创建");
            }
        }
    }
    
    

    在这里插入图片描述

    利用bean的生命周期中的扩展点

    @AutoConfigureOrder

    @AutoConfigureOrder只能改变外部依赖的@Configuration的顺序。
    这是不对的用法

    @Slf4j
    @Configuration
    @ConfigurationProperties(prefix = "dict")
    public class SpringConfig {
        @Component
        @AutoConfigureOrder(1)
        public class Event{
            public Event(){
                System.out.println("事件事件");
            }
        }
    
        @Component
        @AutoConfigureOrder(2)
        public class EventSource{
            public EventSource(Event e){
                System.out.println("事件源创建");
            }
        }
    
    
        @Component
        @AutoConfigureOrder(3)
        public class EventTListener {
    
            public EventTListener(){
                System.out.println("监听器创建");
            }
        }
    }
    

    在这里插入图片描述
    以上内容发现,在config里配置是不起作用的。
    这是正确的用法

    1. 创建两个配置类
    @Slf4j
    @Configuration
    @AutoConfigureOrder(1)
    public class SpringConfig {
        @Component
        public class Event{
            public Event(){
                System.out.println("首先在SpringConfig");
            }
        }
    
    }
    
    
    @Slf4j
    @Configuration
    @AutoConfigureOrder(2)
    public class NewConfig {
        @Component
        public class Event{
            public Event(){
                System.out.println("然后在NewConfig");
            }
        }
    }
    
    1. 测试
      在这里插入图片描述
      发现结果是不正确的,注解还是没有生效。
    2. 当前工程里增加配置 META-INF/spring.factories,内容为项目中的配置类
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.sinosoft.springbootplus.common.config.NewConfig,com.sinosoft.springbootplus.common.config.SpringConfig
    
    
    1. 测试结果如图(正确)
      在这里插入图片描述

    三、遇到的问题:

    1、需要根据配置决定生成哪个实现类。

    在这里插入图片描述
    当在配置文件中配置的dict.cacheType的值是local时,初始化LocalISysDictRepository交给spring容器管理;当项目依赖了redis并且配置文件中配置的dict.cacheType的值是redis时,初始化RedisISysDictRepository交给spring容器管理。
    2、但是我又在这两个实现类上加了@Repository注解,也要交给Spring管理,这个时候项目启动就报错了。(通俗的来说一个类只能一次交给Spring管理)
    在这里插入图片描述

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 653,726
精华内容 261,490
关键字:

加载顺序

友情链接: isocalendar.zip