JDK9~17+Springboot3 @Resource常见问题和解决方案

news2025/2/1 19:58:53

一、常见问题描述

因为JDK版本升级的改动,在Jdk9~17环境下,搭建Springboot项目,会出现原有@Resource(javax.annotation.Resource)不存在的问题,导致项目从Jdk8迁移到高版本时遇到的问题

原因

你可能会问,为什么javax.annotation.Resource注解不存在呢?

 从Jdk9开始,JavaEE从Jdk中分离,jdk就移除掉了javax.annotation.jar包的默认集成,从而导致版本不兼容。所以一旦spring项目从JDK8升到高版本,都会出现javax.annotation.Resource无法引用报红。

java EE 即 java Enterprise Edition,企业级应用,目标是制定一系列企业级应用的标准服务。常见的 javax.servletjavax.annotation

Oracle 收购了创造 java 的 SUN 公司,Oracle 又不想发展 java EE 了,就把 java EE 交给 Eclipse 社区了,但是又因为不知名的原因,禁止社区使用 javax 这个名字。所以,javax.servlet 就变成了 jakarta.servletjakarta.annotation。api无法向前兼容。

 java ee 的最后一个版本也是 8,以后就再也没有 java ee 的新版本

二、各版本出现的问题和解决方案

2.1 Jdk9以上、Springboot3/Spring6.0以前版本的问题

解决方案:

1、手动导入javax.annotation包

        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
        </dependency>

 2、降到Jdk8,你发任你发,我用Java8

2.2 Springboot3/Spring6.0以上版本的问题

从Java EE APIs 到 Jakarta EE

Spring Boot 3开始,所有的Java EE Api都需要迁移到Jakarta EE上来。

大部分用户需要修改import相关API的时候,要用jakarta替换javax。比如:原来引入javax.servlet.Filter的地方,需要替换为jakarta.servlet.Filter

但是当Spring版本升级到6.0以上的版本,即使手动引入javax.annotation包,但是还是会有问题,你会发现类无法注入,导致引用的类is Null,报空指针。

因为Spring也放弃了javax.annotation.Resource注解的支持,而是对jakarta.annotation.Resource注解的支持

private InjectionMetadata buildResourceMetadata(Class<?> clazz) {
        if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
            return InjectionMetadata.EMPTY;
        } else {
            List<InjectedElement> elements = new ArrayList();
            Class targetClass = clazz;

            do {
                List<InjectedElement> currElements = new ArrayList();
                ReflectionUtils.doWithLocalFields(targetClass, (field) -> {
                    if (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
                        if (Modifier.isStatic(field.getModifiers())) {
                            throw new IllegalStateException("@EJB annotation is not supported on static fields");
                        }

                        currElements.add(new CommonAnnotationBeanPostProcessor.EjbRefElement(field, field, (PropertyDescriptor)null));
                    } else if (field.isAnnotationPresent(Resource.class)) {
                        if (Modifier.isStatic(field.getModifiers())) {
                            throw new IllegalStateException("@Resource annotation is not supported on static fields");
                        }

                        if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
                            currElements.add(new CommonAnnotationBeanPostProcessor.ResourceElement(field, field, (PropertyDescriptor)null));
                        }
                    }

                });
                ReflectionUtils.doWithLocalMethods(targetClass, (method) -> {
                    Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                    if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                        if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                            if (ejbClass != null && bridgedMethod.isAnnotationPresent(ejbClass)) {
                                if (Modifier.isStatic(method.getModifiers())) {
                                    throw new IllegalStateException("@EJB annotation is not supported on static methods");
                                }

                                if (method.getParameterCount() != 1) {
                                    throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
                                }

                                PropertyDescriptor pdx = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                                currElements.add(new CommonAnnotationBeanPostProcessor.EjbRefElement(method, bridgedMethod, pdx));
                            } else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
                                if (Modifier.isStatic(method.getModifiers())) {
                                    throw new IllegalStateException("@Resource annotation is not supported on static methods");
                                }

                                Class<?>[] paramTypes = method.getParameterTypes();
                                if (paramTypes.length != 1) {
                                    throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
                                }

                                if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
                                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                                    currElements.add(new CommonAnnotationBeanPostProcessor.ResourceElement(method, bridgedMethod, pd));
                                }
                            }
                        }

                    }
                });
                elements.addAll(0, currElements);
                targetClass = targetClass.getSuperclass();
            } while(targetClass != null && targetClass != Object.class);

            return InjectionMetadata.forElements(elements, clazz);
        }
    }

通过跟代码进去,发现@Resouce的源代码是 jakarta.annotation下的

package jakarta.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Resources.class)
public @interface Resource {
    String name() default "";

    String lookup() default "";

    Class<?> type() default Object.class;

    Resource.AuthenticationType authenticationType() default Resource.AuthenticationType.CONTAINER;

    boolean shareable() default true;

    String mappedName() default "";

    String description() default "";

    public static enum AuthenticationType {
        CONTAINER,
        APPLICATION;

        private AuthenticationType() {
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/631186.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TiDB亿级数据亚秒响应查询将MySql数据全量迁移到TiDB

目录 1 下载安装TiDB工具包1.1 检查最新版本1.2 下载tidb-toolkit 2 Dumpling导出数据2.1 Dumpling工具简介2.2 导出需要的权限2.3 创建用户并授权2.4 验证数据库2.5 导出sql文件2.6 查看导出文件 3 TiDB Lightning导入数据3.1 TiDB Lightning简介3.2 TiDB Lightning 整体架构3…

蓝桥杯【第14届国赛】Python B组

本题解仅代表个人观点&#xff0c;仅供参考&#xff0c;欢迎各位指正 A&#xff1a;弹珠堆放 【问题描述】 小蓝有 20230610 颗磁力弹珠&#xff0c;他对金字塔形状尤其感兴趣&#xff0c;如下图所示&#xff1a; 高度为 1 的金字塔需要 1 颗弹珠&#xff1b; 高度为 2 的金字…

【Jetpack】使用 Room 中的 Migration 升级数据库异常处理 ( 多个数据库版本的迁移 | fallbackToDestructiveMigration() 函数处理升级异常 )

文章目录 一、Room#Migration 迁移工具升级数据库二、多个数据库版本的迁移三、数据库异常处理 - RoomDatabase.Builder#fallbackToDestructiveMigration() 函数四、完整代码示例 一、Room#Migration 迁移工具升级数据库 Room Migration 数据库迁移工具 是 Android Jetpack Arc…

【AI实战营第二期】第三次作业——基于 RTMDet 的气球检测(包含数据集)

作业&#xff1a;基于 RTMDet 的气球检测 背景&#xff1a;熟悉目标检测和 MMDetection 常用自定义流程。 任务&#xff1a; 基于提供的 notebook&#xff0c;将 cat 数据集换成气球数据集; 按照视频中 notebook 步骤&#xff0c;可视化数据集和标签; 使用MMDetection算法库…

01_Linux字符设备驱动开发

目录 字符设备驱动简介 驱动模块的加载和卸载 字符设备注册与注销 实现设备的具体操作函数 添加LICENSE和作者信息 Linux设备号的组成 设备号的分配 chrdevbase字符设备驱动开发实验 创建VSCode工程 添加头文件路径 编写实验程序 C库文件操作基本函数 编写测试APP…

苹果Vision Pro正式发布,下一个iPhone诞生了?

在库克即将退休之际&#xff0c;苹果开启了下一个十年。 2023年6月6日&#xff0c;在苹果WWDC开发者大会上&#xff0c;苹果发布了15寸的MacBook Air&#xff0c;以及一众iOS 17、iPad OS 17、Mac OS等系统的更新。当我们觉得这些常规更新有点不痛不痒&#xff0c;甚至想大呼“…

​selenium中元素定位正确但是操作失败,6种解决办法全稿定

selenium中元素定位正确但是操作失败的原因无外乎以下4种&#xff1a; 一、页面没加载好 解决方法&#xff1a;添加等待方法&#xff0c;如&#xff1a; time.sleep() 二、页面提交需要等待给数据后台 解决方法&#xff1a;添加等待方法&#xff0c;如&#xff1a; time.sl…

一套完整的三甲医院医学影像科PACS系统源码

一、PACS系统概述&#xff1a; 基于VC MSSQL开发的一套三甲医院医学影像PACS系统源码&#xff0c;集成3D影像后处理技术和功能&#xff0c;包括三维多平面重建、三维容积重建、三维表面重建、三维虚拟内窥镜、最大/小密度投影、心脏动脉钙化分析等能满足影像科功能。 二、PAC…

C/C++ 作用域,生命周期,执行线程的概念

相互影响 在C中&#xff0c;对象的生命周期、作用域和执行线程是三个相互关联但又相对独立的概念。它们共同决定了对象在程序中的行为和状态。下面我将详细解释这三个概念以及它们之间的关系和互相影响。 生命周期&#xff1a;对象的生命周期是指从对象被创建&#xff08;构造…

Python暑假自律打卡学习班,免费,速来(2)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 和猫妹学Python&#xff0c;一起趣味学编程。 很快就放暑假了&#xff0c;还有20多天吧&#xff01; 猫妹对这个暑假相当期待啊&#xff0c; 想想今年的五一劳动节有多火爆…

仙境传说RO:npc汉化方法

仙境传说RO&#xff1a;npc汉化方法 大家好我是艾西&#xff0c;在我们说了那么多期的教程中大家应该有发现游戏内很多都还是英文的&#xff0c;如果对于国内的玩家开展这个游戏可能有些不熟悉的小伙伴玩起来会有点难受&#xff0c;今天艾西跟大家分享下怎么汉化NPC等。 我们…

异常数据检测 | Python实现基于高斯概分布的异常数据检测

文章目录 文章概述模型描述源码分享学习小结参考资料文章概述 高斯分布也称为正态分布。它可以被用来进行异常值检测,不过我们首先要假设我们的数据是正态分布的。不过这个假设不能适应于所有数据集。但如果我们做了这种假设那么它将会有一种有效的方法来发现异常值。 模型描述…

多元分类预测 | Matlab人工蜂群算法(ABC)优化随机森林(RF)的分类预测,ABC-RF分类预测模型,多输入单输出模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab人工蜂群算法(ABC)优化随机森林(RF)的分类预测,ABC-RF分类预测模型,多输入单输出模型 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,…

「一文讲透」快消行业营销数字化转型

历经疫情的洗礼&#xff0c;各行业都在开启新一轮市场需求的盘点&#xff0c;无论消费者习惯、市场零售终端还是渠道分销。在供需变革、消费升级、服务传达诸多方面&#xff0c;都对品牌商产-营-销-服系统化管理提出了新的挑战。 面对激烈的市场环境竞争&#xff0c;品牌商核心…

代码随想录第56天

1.两个字符串的删除操作 动规五部曲&#xff0c;分析如下&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j]&#xff1a;以i-1为结尾的字符串word1&#xff0c;和以j-1位结尾的字符串word2&#xff0c;想要达到相等&#xff0c;所需要删除元…

2023了,软件测试如何获得高薪?

做自动化测试后悔吗&#xff1f; 后悔&#xff0c;真的后悔&#xff01; 后悔没有早点学..... 虽然到处都在散播35的焦虑&#xff0c;姑且信之&#xff0c;那么反问你&#xff0c;如果你30岁了&#xff0c;那么给你5年&#xff0c;能够在某个领域成为专家呢&#xff1f;希望你…

『手撕 Mybatis 源码』05 - SqlSession 执行主流程

SqlSession 执行主流程 获取 BoundSql 经过加载完所有配置之后&#xff0c;继续梳理执行 sql 的过程 public class MybatisTest {Testpublic void test1() throws IOException {...// 4. 委派给 Executor 来执行&#xff0c;Executor 执行时又会调用很多其他组件&#xff08…

ceph分布式存储

1、存储基础 //单机存储设备 ●DAS&#xff08;直接附加存储&#xff0c;是直接接到计算机的主板总线上去的存储&#xff09; IDE、SATA、SCSI、SAS、USB 接口的磁盘 所谓接口就是一种存储设备驱动下的磁盘设备&#xff0c;提供块级别的存储 ●NAS&#xff08;网络附加存储&am…

LCHub 6 月低代码平台排行榜发布

LCHub低代码平台排行榜 2023 国产低代码名录和产品信息一览 2023国产低代码平台排行榜 低代码最新视频课程 最新解读报告:2023年6月低代码平台排行榜:维格表 伙伴云上升最快 共有120个低代码平台参与排名, 点击查看排名规则更新 TOP 10 低代码平台 6月 LCHub 指数走势

【linux基础15】用户管理

文章目录 一. 用户和组1. 用户和组介绍用户分类UIDGID 2. /etc/passwd和/etc/shadow用户信息文件&#xff1a;密码文件&#xff1a; 二、linux账号管理1. 用户操作1.1. 新增用户1.2. 指定UID、添加所属组、执行家目录1.3. 设置密码&#xff1a;passwd1.4 修改用户家目录&#x…