当前位置: 首页 > 面试题库 >

为什么我的Spring @Autowired字段为空?

龙弘济
2023-03-14
问题内容:

我有一个具有字段()的Spring @Service类(MileageFeeCalculator),但是该字段是我尝试使用它时所用的。日志显示该bean和该bean都在创建,但是每当我尝试在服务bean上调用该方法时,都会得到一个a 。Spring为什么不自动接线该领域?@AutowiredrateServicenullMileageFeeCalculatorMileageRateServiceNullPointerExceptionmileageCharge

控制器类:

@Controller
public class MileageFeeController {    
    @RequestMapping("/mileage/{miles}")
    @ResponseBody
    public float mileageFee(@PathVariable int miles) {
        MileageFeeCalculator calc = new MileageFeeCalculator();
        return calc.mileageCharge(miles);
    }
}

服务等级:

@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
    }
}

应该自动连接的服务bean,MileageFeeCalculator但不是:

@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)
    ...

问题答案:
本文向大家介绍为什么我的Spring @Autowired字段为空?相关面试题,主要包含被问及为什么我的Spring @Autowired字段为空?时的应答技巧和注意事项,需要的朋友参考一下

带注释的字段@Autowirednull因为Spring不了解MileageFeeCalculator你使用其创建的副本,new也不知道自动对其进行接线。

Spring Inversion of Control(IoC)容器具有三个主要的逻辑组件:ApplicationContext应用程序可以使用的组件(bean)的注册表(称为),配置器系统通过匹配对象将对象的依赖项注入到它们中在上下文中具有bean的依赖关系,以及一个依赖关系解决程序,它可以查看许多不同bean的配置并确定如何以必要的顺序实例化和配置它们。

IoC容器不是魔术,除非你以某种方式告知Java对象,否则它无法了解Java对象。当你调用时new,JVM实例化新对象的副本并将其直接交给你-它从未经历配置过程。你可以通过三种方式配置bean。

我已经在GitHub项目上使用Spring Boot启动了所有这些代码;你可以针对每种方法查看一个正在运行的项目,以查看使其工作所需的一切。用标记NullPointerException:nonworking

Inject your beans

最可取的选择是让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 bean scopes使用注入。

通过注入@MileageFeeCalculator服务对象起作用的标记:working-inject-bean

Use@Configurable

如果确实需要new自动创建的对象,则可以将Spring @Configurable注释与AspectJ编译时编织一起使用以注入对象。这种方法将代码插入到对象的构造函数中,以警告Spring正在创建它,以便Spring可以配置新实例。这需要在构建中进行一些配置(例如使用进行编译ajc)并打开Spring的运行时配置处理程序(@EnableSpringConfigured使用JavaConfig语法)。Roo Active Record系统使用此方法来允许new你的实体实例获取注入的必要持久性信息。

@Service
@Configurable
public class MileageFeeCalculator {

    @Autowired
    private MileageRateService rateService;

    public float mileageCharge(final int miles) {
        return (miles * rateService.ratePerMile());
    }
}

通过@Configurable在服务对象上使用而起作用的标记:working-configurable

Manual bean lookup: not recommended

这种方法仅适用于在特殊情况下与遗留代码接口。几乎总是最好创建一个Spring可以自动连接并且遗留代码可以调用的Singleton适配器类,但是可以直接向Spring应用程序上下文请求一个bean。

为此,你需要一个Spring可以引用该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);
    }
}

通过在Spring上下文中手动查找服务对象而起作用的标记: working-manual-lookup



 类似资料:
  • 我在使用新的模型和映射器时再次遇到了这个问题。我试图理解为什么我的Spring@autowired场是空的?和代码示例,但它仍然是null!我尝试了、、。 MyBatis 3.4.5、MyBatis Spring 1.3.1、MyBatis Spring Boot Autoconfigure 1.3.1、MyBatis Spring Boot Starter 1.3.1

  • 我有一个带有的spring boot应用程序。 我还使用并在其中扩展。 当我尝试@AutoWired我拥有的服务时: 原因:org.springframework.beans.factory.noSuchBeanDefinitionException:没有“com.api.core.service.countryService”类型的合格bean可用:应至少有一个合格的自动候选bean。依赖项注释

  • 我试图在配置类中定义datasource和jdbctemplate bean。然而,每当我将它们自动连接到Restcontroller类时,它们都会为null。为什么? 在我的配置类中 restcontroller类内部 每次尝试编译时,我都会收到来自autowired字段的空指针异常,即使我没有手动实例化任何内容,只是让spring通过自动连线来管理所有实例。

  • 我有一个实现MessageListener的类,用于Spring Data Redis。它在Redis上运行良好,但我有一个奇怪的行为。我有一个test()方法来测试MessageService实例是否为空。它需要调用Jpa Repository以获取MySql DB中的持久性。奇怪的行为是,如果在getNewMessage()和printWelcome()方法中调用它,它就不会为空(然后我可以使

  • 问题内容: 我有这段简单的代码。 当我运行上面的代码时,该对象被打印为null。(我得到 “ Object = null” ) 令人惊讶的是,在类Y中,当我删除null声明时 打印对象的实际值。 类似于( “ Object = java.lang.Object@3cd1a2f1” )之 类的现象为何被观察到?“这个”指的是什么?如果仅声明对象,则将其初始化为null,那么为什么会有这种异常行为呢?

  • 问题内容: 我正在努力从以下代码中获取正确的输出: 游乐场片段 打印时,结构字段为空。我敢肯定某个地方有一个愚蠢的错误,但是我仍然对Go还是陌生的,而且我已经在这里呆了几个小时。请帮忙。 问题答案: 这已经出现了很多次了。问题在于只能对导出的字段进行封送处理。 通过以大写(大写)字母开头来导出结构域。 在Go Playground上尝试一下。 请注意,JSON文本包含带有小写字母文本的字段名称,但