Spring自动注入失败的解决方法
作者:梅长酥 发布时间:2022-08-13 03:41:31
目录
Spring自动注入失败如何解决?
回答
注入你的bean
使用@Configurable
手动查找bean:不推荐
Spring自动注入失败如何解决?
我有一个被Spring @Service注解的类(MileageFeeCalculator),它有一个用@Autowired注入的变量(rateService),但是当我用这个变量的时候,它显示为null。日志显示MileageFeeCalculator bean和MileageRateService bean都被创建了,但是当我调用service上的mileageCharge ()方法时,就会报NullPointerException错误。为什么Spring不能自动注入这个实例?
Controller:
@Controller
public class MileageFeeController {
@RequestMapping("/mileage/{miles}")
@ResponseBody
public float mileageFee(@PathVariable int miles) {
MileageFeeCalculator calc = new MileageFeeCalculator();
return calc.mileageCharge(miles);
}
}
Service:
@Service
public class MileageFeeCalculator {
@Autowired
private MileageRateService rateService; // <--- should be autowired, is null
public float mileageCharge(final int miles) {
return (miles * rateService.ratePerMile()); // <--- throws NPE
}
}
本应被注入Service但是并没有的类
@Service
public class MileageRateService {
public float ratePerMile() {
return 0.565f;
}
}
为什么我调用GET /mileage/3这个请求的时候,会报这样的错误:
java.lang.NullPointerException: null
at com.chrylis.example.spring_autowired_npe.MileageFeeCalculator.mileageCharge(MileageFeeCalculator.java:13)
at com.chrylis.example.spring_autowired_npe.MileageFeeController.mileageFee(MileageFeeController.java:14)
...
回答
@Autowired注解的字段为null是因为,Spring无法获取你用new关键字创建的类,也无法自动注入它。
Spring Ioc容器有三个主要的逻辑组件:应用程序可以使用的注册表(ApplicationContext);通过把依赖项与上下文中的bean匹配,将依赖的对象注入的配置器系统;以及一个依赖解析器,它可以查看许多不同bean的配置,并确定如何按必要的顺序实例化和配置它们。
Ioc容器并没有魔法,除非你以某种方式通知它,否则它无法获取Java对象。当你调用new创建对象时,JVM实例化新对象,并将其中一个副本交给你——它并不经历Spring的配置过程。有三种方法可以配置bean实例。
注入你的bean
最好的选择是让Spring注入所有的bean;这样的代码量会最少并且也最容易维护。为了使注入如你所愿,需要把MileageFeeCalculator像这样注入。
@Controller
public class MileageFeeController {
@Autowired
private MileageFeeCalculator calc;
@RequestMapping("/mileage/{miles}")
@ResponseBody
public float mileageFee(@PathVariable int miles) {
return calc.mileageCharge(miles);
}
}
如果你需要为不同的请求都创建一个类的新实例,可以通过Spring注解的scopes实现。
使用@Configurable
如果你真的需要把new出来的对象保存进行注入,那可以使用Spring的@Configurable注解,通过使用AOP在编译时织入你的对象中。这种方法将代码插入到对象的构造函数中,提醒Spring这个对象正在被创建,这样Spring就能够配置新实例了。这需要你添加一些配置信息。并打开Spring的运行时配置处理器。Roo Active Record系统使用这种方法来允许实体的new实例获取注入的必要持久性信息。
@Service
@Configurable
public class MileageFeeCalculator {
@Autowired
private MileageRateService rateService;
public float mileageCharge(final int miles) {
return (miles * rateService.ratePerMile());
}
}
手动查找bean:不推荐
这种方法只适用于在特殊情况下与遗留代码对接。创建一个Spring可以自动注入并且遗留代码也能调用的单例适配器总是可取的,但是也许可以直接向spring application context请求bean实例。
为了做到这点,你需要一个类,该类提供了对ApplicationContext对象的引用
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext() {
return context;
}
}
之后你的遗留代码就可以调用getContext()方法获取所需的bean实例了。
@Controller
public class MileageFeeController {
@RequestMapping("/mileage/{miles}")
@ResponseBody
public float mileageFee(@PathVariable int miles) {
MileageFeeCalculator calc = ApplicationContextHolder.getContext().getBean(MileageFeeCalculator.class);
return calc.mileageCharge(miles);
}
}
来源:https://juejin.cn/post/6960856715621302286


猜你喜欢
- EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。ehcach
- 这篇文章主要介绍了springboot2.0如何通过fastdfs实现文件分布式上传,文中通过示例代码介绍的非常详细,对大家的学习或者工作具
- 本文实例讲述了Android编程处理窗口控件大小,形状,像素等UI元素工具类。分享给大家供大家参考,具体如下:/*** 处理窗口控件大小,形
- 本节我们开始自我实现我们自己okhttp框架中的每个 * 。先简单回顾一下各个 * 的作用:RetryAndFollowUpIntercep
- 本例是利用C#中的性能计数器(PerformanceCounter)监控网络的状态。并能够直观的展现出来涉及到的知识点:Performanc
- 以下摘自胖哥分享的 2022开工福利教程。在学习Spring Security的时候你有没有下面这两个疑问:Spring Security的
- Excel表格中,由于各种数据的复杂性,可能存在单元格中的数据字号大小、数据内容长度不一而出现,列宽过宽、过窄或者行高过大、过小的问题。常见
- 导读导读 | 12月总体来说互联网的技术圈是非常热闹的,chatGPT爆火,SpringBoot3.0发布等重磅陆消息续进入大家的视线,而本
- 需求:接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承实体类(concrete class)?抽象类中是否
- 前面文章讲述了Android手机与BLE终端之间的通信,而最常见的BLE终端应该是苹果公司倡导的iBeacon基站。iBeacon技术基于B
- 线程池模型一般的池化模型会有两个方法,用于获取资源和释放资源,就像这样:public interface XXPool{ &n
- 本文的目的是用springboot整合mybatis实现一个简单的一对多查询。(查询一个用户有多少件衣服)第一步:数据库中,可以直接在nav
- 一、事务隔离级别①介绍数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事 务与其他事务隔离的程度称为
- .Net的System.Net.Sockets.TcpClient和System.Net.Sockets.Socket都没有直接为Conne
- 一:问题引入前面讲到用户支付完成之后微信支付服务器会发送回调通知给商户,商户要能够正常处理这个回调通知并返回正确的状态码给微信支付后台服务器
- 本文主要讲解安装AndroidStudio和配置环境变量遇到一些问题,以及解决方法。需要的软件:AndriodStudio安装包.java
- 一、观察者模式基本概况1.概念观察者模式(Observer Design Pattern)也被称为发布订阅模式(Publish-Subcri
- 目录前言基础组件工作流程初步使用详细流程获取 MapperProxy 对象缓存执行方法构造参数获取需要执行的 SQL 对象执行 SQL 语句
- 前几天工作中一段业务代码需要一个变量每天从1开始递增。为此自己简单的封装了一个线程安全的计数器,可以让一个变量每天从1开始递增。当然了,如果
- 一.背景本文主要介绍Java 8中时间的操作方法java.util.Date是用于表示一个日期和时间的对象(注意与java.sql.Date