pro1
原因在于这里重构后,但是没有更改扫描的范围,导致ORM的MAPPER层无法被扫到
修改后即可
pro2
jwtTokenProvider 为 null:确保 jwtTokenProvider 被正确注入。
token 为 null:虽然代码已经检查了 token 是否为 null,但 jwtTokenProvider.resolveToken(request) 可能返回 null,这会导致后续的 jwtTokenProvider.validateToken(token) 抛出 NullPointerException。
username 为 null:如果 jwtTokenProvider.getUsernameFromToken(token) 返回 null,则 userDetailsService.loadUserByUsername(username) 会抛出 NullPointerException。
userDetails 为 null:如果 userDetailsService.loadUserByUsername(username) 返回 null,则 new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()) 会抛出 NullPointerException。
jwtTokenProvide为什么没有被触发?
jwtFilter触发了,但是jwtTokenProvider并没有被触发,在filter使用provider的resolveToken方法时
“不建议使用字段注入 ”
在Spring中依赖注入有三大类:字段注入、构造器注入、Setter方法注入。
字段注入是将Bean作为字段注入到类中,也是最方便,用的最多的注入方式
getOrder方法里调用了使用注入对象,这样执行结果为空指针异常,这就是字段注入的第一个问题:对象的外部可见性,无法在容器外部实例化TestHandleService(例如在测试类中无法注入该组件),类和容器的耦合度过高,无法脱离容器访问目标对象
通过构造器的方式将Bean注入到字段中。
构造器注入能够保证注入的组件不可变,并且确保需要的依赖不为空。
这样就可以将变量设置为final,并且传递的肯定是一个对象,避免出现空指针异常。
若是出现字段注入中循环依赖的问题,在项目启动时Spring会非常形象的将错误抛出来:
在 Spring 框架中,字段注入(Field Injection)虽然使用方便,但并不推荐作为最佳实践。以下是几个主要原因:
1. 可测试性差
单元测试困难:使用字段注入时,依赖项是在运行时由 Spring 容器自动注入的,这使得在编写单元测试时很难模拟这些依赖项。你需要使用复杂的工具(如 Mockito)来模拟这些依赖项,增加了测试的复杂性。
构造函数注入更清晰:通过构造函数注入,你可以显式地传递依赖项,使得对象的创建过程更加清晰,更容易进行单元测试。
2. 不可变性和线程安全性
不可变性:构造函数注入允许你在对象创建时设置所有必需的依赖项,从而确保对象的不可变性。一旦对象创建完成,其状态就不会改变,这有助于提高代码的线程安全性。
字段注入可能导致空指针异常:如果依赖项没有被正确注入,字段可能会是 null,从而导致 NullPointerException。
对象外部可见性:当使用字段注入时,对象只能通过Spring容器来实例化和管理,因为只有Spring容器能够正确地初始化这些依赖。这意味着如果尝试在容器外部创建此类的对象(例如,在单元测试中),则可能会遇到空指针异常,因为依赖项没有被正确注入
-
可能导致循环依赖:字段注入容易引发循环依赖的问题,即两个或多个Bean相互依赖对方作为构造参数。尽管Spring可以通过设置某些属性来处理这种循环引用,但这增加了系统的复杂性和潜在的风险
1
。 -
无法设置为final或静态变量:由于字段注入是在类实例化之后由Spring容器自动完成的,因此不能将需要注入的字段声明为
final
或static
。这限制了代码的设计灵活性,并且违反了良好的面向对象编程实践,如不可变性原则1
。 -
破坏封装性和可测试性:字段注入使得类的内部状态对外部世界开放,因为它允许从外部直接访问和修改私有成员。此外,它也降低了类的可测试性,因为在编写单元测试时,你必须依赖于Spring容器来设置所有必要的依赖,而不是简单地传递所需的依赖给构造函数或setter方法
2
。 -
容易违反单一职责原则:由于字段注入的便利性,开发人员可能会倾向于在一个类中引入过多的依赖,从而使得该类承担了过多的责任,违背了单一职责原则
7
。 -
与特定IOC框架强耦合:使用字段注入会增加类对Spring容器的依赖程度,使得这些类难以与其他非Spring环境集成,或者在不需要完整Spring上下文的情况下运行
6
。
什么时候可以使用字段注入
尽管存在上述缺点,但在某些情况下,字段注入仍然是一个合理的选择:
-
简化配置:对于那些小型项目或简单的组件,字段注入可以减少样板代码的数量,使代码更加简洁明了。特别是当依赖关系较少且明确时,字段注入可以快速实现功能而不必担心复杂的构造函数或setter方法
12
。 -
遗留系统迁移:在将旧有的基于XML配置的Spring应用迁移到注解驱动的方式时,字段注入可以帮助平滑过渡,尤其是在逐步替换现有代码的过程中。此时,开发者可以先用字段注入替换掉XML中的bean定义,然后再考虑是否要重构为更推荐的构造器或setter注入
14
。 -
原型模式或实验性开发:在进行快速原型开发或是探索性的研究阶段,字段注入可以加快迭代速度,让开发者专注于核心逻辑而非基础设施细节。然而,一旦确定了设计方案,应该重新评估并可能转换为更稳健的注入方式
13
。 -
辅助性依赖:对于一些辅助性的、非关键路径上的依赖,字段注入可能是可行的选项。例如,日志记录器、事件发布者等服务通常不会影响主要业务流程,因此即使它们未被正确注入,也不会导致严重的后果
14
。
移除 @Autowired 注解:不再使用 @Autowired 注解在字段上。
添加构造器:添加一个构造器,通过构造器参数注入 JwtTokenProvider、UserDetailsService 和 AuthService。
初始化字段:在构造器中初始化这些字段。
pro3
pro4
枚举量的使用
无法实例化枚举类型“?
在 Java 中,枚举类型不能通过 new 关键字进行实例化。枚举类型的实例是在枚举定义时自动创建的,并且是单例的
需要使用枚举类型中已经定义的常量。假设 request.getUserType() 返回的是一个字符串,你可以通过 Enum.valueOf 方法将字符串转换为对应的枚举常量。以下是修改后的代码:
request.getUserType(): 假设这个方法返回的是一个字符串,例如 "student"。
.toUpperCase(): 将字符串转换为大写,因为枚举常量通常是大写的,例如 STUDENT。
UserType.valueOf(...): 使用 valueOf 方法将字符串转换为对应的枚举常量。
在枚举类中定义了字符串和枚举的映射关系,为什么没用上?
通过 getType 方法可以获取与枚举常量关联的字符串值。
通过 fromString 方法可以根据字符串值查找对应的枚举常量。
就是先使用 fromString 获取到相应的 Type,然后再传入
pro5
错误 java.sql.SQLException: Data truncated for column 'user_type' at row 1 表明在尝试将数据插入到数据库表的 user_type 列时,数据被截断了。这通常是因为插入的数据长度超过了该列定义的最大长度,或者插入的数据不符合该列的数据类型要求。
就是JAVA枚举类和数据库枚举类的概念要区分,以及JPA和Mybatis-Plus是两种作ORM的框架,用JPA简单点,可以直接
@Enumerated(EnumType.STRING)
将Java枚举类转为string映射到数据库字段当中,如果不用就会报错;Mybtatis-Plus好像要用一个EnumHandler