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

如何在Springboot中调用方法

齐嘉庆
2023-03-14
问题内容

注意:这旨在作为常见问题的规范答案。

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

控制器类:

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

问题答案:

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

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

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

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

注入你的豆子

最可取的选择是让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

使用@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

手动查找Bean:不建议

这种方法仅适用于在特殊情况下与遗留代码接口。几乎总是最好创建一个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



 类似资料:
  • 我想在intellij Idea中以调试模式启动spring-boot maven应用程序,但当我创建断点时,应用程序不会挂起,而是会继续。我读了很多题目,但还是不明白怎么做。你能帮我决定最好的行动方案吗。 但是当请求LocalHost:5005/MyPage时,我会出现错误101(NET::ERR_CONNECTION_RESET)。似乎有些maven参数没有指定。 下面是我在pom.xml中的

  • 这是我的豆子 这是我的路线 您可能会在上面的路由中找到一些语法问题,但它工作正常(此处复制的代码不准确) 想知道,我们可以看到bean正在路由中使用,这是类的一个实例,但是它是如何在路由中调用方法的呢?路由是如何知道调用和打印哪个方法的?

  • 我需要在Springboot中实现多线程,同时使用POST方法调用API。我根据一个SELECT查询从oracle数据库中提取记录,然后使用行映射器逐个遍历每个记录。在下一步中,我只调用一个方法将这些记录发送到API,以postmapping的形式发送这些记录并取回记录。 因为select查询一次可以返回10、20或100条记录。逐个调用每条记录并不理想。我在想我是否可以一次发送多个记录。我不知道

  • 这是我的登录名。xhtml文件 这是我的课 为什么会出现这个异常,这是什么意思?我以前在命令按钮中使用过h标签,但它不起作用 原因:javax。面孔。艾尔。MethodNotFoundException:javax。艾尔。MethodNotFoundException:/index。xhtml@23,80 action=“#{loginBean.validate}”:未找到方法:ritu。登录。U

  • 问题内容: 如何使用反射调用带有参数的方法? 我想指定这些参数的值。 问题答案: 这是一个使用涉及原语的反射调用方法的简单示例。 要健壮,应该捕获和处理所有检查反射有关的异常,,。

  • 如何启用此处列出的ExecutorServiceMetrics? https://github.com/micrometer-metrics/micrometer/blob/master/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/ExecutorServiceMetrics.java SpringB