技术标签: spring jvm java maven jar SpringBoot
- 为什么打开部分字节码文件(.class)文件,看到部分类报红,找不到该类,难道真的没有该类?那编译的时候不报错吗?
- Spring在启动的时候为什么会可以正常启动,没有该类还能正常启动?Spring是如何加载和处理这些类的呢?
- 项目启动后,该类会被JVM加载初始化吗?
这里我随便找了一个类,里面包含一些没有的class,见下图
发现字节码文件(RxReactiveStreams.class)不存在,那我在另外一个比较完整的项目,找到该类属于[rxjava-reactive-streams-1.2.1.jar]包下面的
这时候我回到本项目,探讨本项目的pom中是否包含此[rxjava-reactive-streams-1.2.1.jar]
借助于IDEA插件MavenHelper在【spring-cloud-openfeign-core-2.2.5.RELEASE.pom】中找到相关引用
简单说明下:
- 这是关键: o p t i o n a l 为 t r u e 的 话 作 用 是 让 新 项 目 依 赖 本 项 目 的 时 候 , 不 去 依 赖 此 j a r 包 , 设 置 f a l s e , 新 项 目 就 会 能 引 用 到 此 j a r 包 \color{red}{optional为true的话作用是让新项目依赖本项目的时候,不去依赖此jar包,设置false,新项目就会能引用到此jar包} optional为true的话作用是让新项目依赖本项目的时候,不去依赖此jar包,设置false,新项目就会能引用到此jar包
- compile,缺省值,适用于所有阶段,会随着项目一起发布。 编译范围依赖在所有的classpath 中可用,同时它们也会被打包
optional为true:这样的话只有直接引用[rxjava-reactive-streams-1.2.1.jar]的jar包才会引到,一些通过间接引用的则不回引用到,这就导致我们看到的时候找不到该class字节码文件;
关于scope、optional详细
- scope的讲解
- optional的讲解
springboot Bean加载分为Bean扫描注册和Bean初始化。
springboot 通过ConfigurationClassBeanDefinitionReader读取@Configuration注解标识的类。在扫描候选资源时,spring并没有通过Classloader#loadClass()来加载class文件,而是通过Classloader.getResource()获得class二进制文件,通过ClassReader对二进制文件进行ASM语法解析,从而得到候选类和注解的元数据。也就是说在spring扫描需要加载的Bean时,所有候选类都没有加载初始化。
当spring获得候选bean的元信息时,需要判断这个bean是否真的需要被加载。这个就是spring的ConditionEvaluator体系。
比如在AnnotatedBeanDefinitionReader#doRegisterBean()中有判断:
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
在获得ConditionalOnClass注解的元数据时还有个特殊处理,我们声明@ConditionalOnClass(A.class)时,使用的是Class类。为了后续操作时不引起class加载,AnnotatedElementUtils#getMergedAnnotationAttributes(element,annotationName,classValuesAsString,nestedAnnotationsAsMap)将class类转换成了class的名称字符串。
在最终判断class是否存在时,jvm其实还是抛出了ClassNotFoundException,只是异常被吞没了。(~ ̄▽ ̄)~
//OnClassCondition$MatchType.isPresent(String, ClassLoader) line: 219
private static boolean isPresent(String className, ClassLoader classLoader) {
//省略若干行
try {
forName(className, classLoader);
return true;
}
catch (Throwable ex) {
return false;//我就在这里,只是你看不到 O(∩_∩)O
}
}
所以关于这个问题的正确说法应该是,class类不存在时spring条件加载能够正常执行,而不是不报异常。
至此,当Class A不存在时,Bean B被注册到spring容器中,等待初始化。
在初始化Bean时,AbstractAutowireCapableBeanFactory#createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)直接通过MethodProxy.invokeSuper()反射调用了C#getBeanB()。C#getBeanA()将永远不会被调用,默默地在角落里死去。。。
- 存在该类,只是我们引用jar【B】包的时候,设置optional为true,也就是说【B】只属于直接上司【A】,【C】jar不能调遣【B】jar,【C】jar也不会引用【B】jar包,想要使用需要我们另外手动引用jar包【B】;这就导致我们没有手动引用【B】时,看不到该类;
- 但是其本项目【A】在编译打包的时候,是可以进行编译的,因为【A】是【B】的直属上司
springboot Bean加载机制和选择机制决定了项目可以正常启动,虽然没有该类,但是我们也没有用到该类呀,这就和Spring加载class字节码文件有关,Spring采用的Classloader.getResource()获得class二进制文件,通过ClassReader对二进制文件进行ASM语法解析,从而得到候选类和注解的元数据。也就是说在spring扫描需要加载的Bean时,所有候选类都没有加载初始化。
当spring获得候选bean的元信息时,需要判断这个bean是否真的需要被加载。这个就是spring的ConditionEvaluator体系。
比如在AnnotatedBeanDefinitionReader#doRegisterBean()中有判断
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
在获得ConditionalOnClass注解的元数据时还有个特殊处理,我们声明@ConditionalOnClass(A.class)时,使用的是Class类。为了后续操作时不引起class加载,AnnotatedElementUtils#getMergedAnnotationAttributes(element,annotationName,classValuesAsString,nestedAnnotationsAsMap)将class类转换成了class的名称字符串。
在最终判断class是否存在时,jvm其实还是抛出了ClassNotFoundException,只是异常被吞没了。(~ ̄▽ ̄)~
//OnClassCondition$MatchType.isPresent(String, ClassLoader) line: 219
private static boolean isPresent(String className, ClassLoader classLoader) {
//省略若干行
try {
forName(className, classLoader);
return true;
}
catch (Throwable ex) {
return false;//我就在这里,只是你看不到 O(∩_∩)O
}
}
本文参考链接:https://blog.csdn.net/swordcenter/article/details/98937826
文章浏览阅读4.8k次,点赞3次,收藏34次。安装华睿相机的驱动:http://download.huaraytech.com/pub/sdk/Ver2.2.3/Windows/2.2.3版本里面增加QT调用的例程,很详细另有Document文件夹下的相关文件文档,配置可以进行参考本文对在调试需求下配置1、环境变量:自动安装的话,环境变量会自动添加,可以不动;2、3、解决方案,添加头文件和使用命名空间..._c++调用华睿工业相机sdk
文章浏览阅读112次。统介绍:1.系统采用主流的 SSM 框架 jsp JSTL bootstrap html5 (PC浏览器使用)2.springmvc +spring4.3.7+ mybaits3.3 SSM 普通java web(非maven, 附赠pom.xml文件) 数据库:mysql3.开发工具:myeclipse eclipse idea 均可, 没有限制. 我这边myeclipse 2014 导出..._spring库存系统
文章浏览阅读1.6k次,点赞26次,收藏18次。伴随着信息技术与互联网技术的不断发展,校园也进到了一个新的信息化时代,传统管理技术性没法高效率、容易地管理自习室预约信息内容。为了实现时代的发展必须,提升自习室预约高效率,各种各样自习室预约体系应时而生,自习室预约管理系统的实现是信息内容时代浪潮时代的产物之一。一切系统都要遵循系统设计的基本流程。它还需要通过市场调查、需求分析报告、汇总设计、详尽设计以及测试,根据node语言表达设计,完成实验室预约管理系统。
文章浏览阅读320次,点赞9次,收藏5次。2024年材料员-通用基础(材料员)证考试题库及材料员-通用基础(材料员)试题解析是安全生产模拟考试一点通结合(安监局)特种作业人员操作证考试大纲和(质检局)特种设备作业人员上岗证考试大纲随机出的材料员-通用基础(材料员)在线模拟考试题练习。对此,正确的处理方式应当是( )。49、【单选题】按照标准制作方法制成边长为150mm的标准立方体试件,在标准条件(温度20℃±2℃,相对湿度为95%以上)下养护( ),然后采用标准试验方法测得的极限抗压强度值,称为混凝土的立方体抗压强度。安全 生产模 拟考试一点通。
文章浏览阅读6.3k次,点赞3次,收藏7次。报错原因:通过报错内容 “TNS:listener does not currently know of SID given in connect descriptor”,可以分析出,SID 不正确;jdbc连接数据库的时候,使用数据库的 sid_name,而不是数据库的 services_name(服务名)原文链接:https://blog.csdn.net/weixin_45894220/article/details/129839666。//监听sid服务,表示sid为orcl。_ora-12505
文章浏览阅读45次。http://www.betool.com.cn/api/qqchat.aspx?qq=862238001替换qq号码即可转载于:https://www.cnblogs.com/max-stone/p/3684688.html_与qq交谈的代码
文章浏览阅读237次。定义一个整型变量num:num是标识符号,也叫变量名称,int是变量类型, 10是初始值可选变量分为两种:基本类型的变量和引用类型的变量。在Java中,所有的变量必须先声明再使用。基本的变量声明方法如下:type是Java的基本类型之一,或类及接口类型的名字。标识符(identifier)是变量的名字,指定一个等号和一个值来初始化变量。请记住初始化表达式必须产生与指定的变量类型一样(或兼容)的变量。声明指定类型的多个变量时,使用逗号将各变量分开;
文章浏览阅读4.1k次,点赞3次,收藏4次。yarn 安装依赖报错 error An unexpected error occurred: https://registry.yarnpkg.com“
文章浏览阅读1.2k次。二、文档注释:输入/**后,按Enter,会自动根据参数和返回值生成注释模板。2.多行注释:Ctrl +Shift+ /一、选中内容然后按需要按快捷键。1.单行注释:Ctrl + /_idea多行注释
文章浏览阅读894次。 这个哥们儿的手指蛮灵活啊,他好像叫balian fabisonghttp://www.videoplayer.es/video/indexthumbs-instructional-balisong-trick-trip-hop-beat/tVAJDI5dRFs/http://www.youtube.com/watch?v=o8_KlXPGHW8http://www.youtube.c
文章浏览阅读928次。聚焦源代码安全,网罗国内外最新资讯!编译:代码卫士Grafana 为其多个应用版本发布安全修复方案,修复了一个严重漏洞,它可使攻击者绕过认证并接管使用 Azure Active Directory 用于认证的任何 Grafana 账户。该漏洞的编号是CVE-2023-3128,CVSS v3.1评分是9.4。Grafana 是一款广泛使用的开源分析和交互可视化 app,通过大量监控平台和应用程序..._grafana6.7.6版本漏洞
文章浏览阅读52次。一、形式:小写{{ name | lower }} 二、过滤器是可以嵌套的,字符串经过三个过滤器,第一个过滤器转换为小写,第二个过滤器输出首字母,第三个过滤器将首字母转换成大写标签{{ str|lower|first|upper }} 三、过滤器的参数显示前30个字{{ bio | truncatewords:"30..._django前台{{ str|upper|lower|upper }}