gpt4 book ai didi

java - 如何在 Spring Boot 2 中检索应用程序上下文

转载 作者:行者123 更新时间:2023-12-02 03:45:32 25 4
gpt4 key购买 nike

我定义了这个 ApplicationContextProvider 类以及 MyApplication.java (应用程序运行的入口点):

package com.company.my.app;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;


@Component
public class ApplicationContextProvider implements ApplicationContextAware {

private ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}

public ApplicationContext getContext() {
return applicationContext;
}
}

拥有包含两个类的包 restapi (Greeting 只是一个保存数据的类):

package com.company.my.app.restapi;

import com.company.my.app.ApplicationContextProvider;
import io.micrometer.core.instrument.Counter;
import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class GreetingController {

private static final Logger LOG = LoggerFactory.getLogger(GreetingController.class);

private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();

@RequestMapping("/greeting")
public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {

ApplicationContextProvider acp = new ApplicationContextProvider();
ApplicationContext context = acp.getContext();

if (context == null) LOG.info("app context is NULL");

Counter bean = context.getBean(Counter.class);
bean.increment();

return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}

最后,MyApplication 类是:

package com.company.my.app;

import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.binder.MeterBinder;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Counter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
public class MyApplication {

@Bean
public MeterBinder exampleMeterBinder() {
return (meterRegistry) -> Counter.builder("my.counter")
.description("my simple counter")
.register(meterRegistry);
}

@Configuration
public class CounterConfig {
@Bean
public Counter simpleCounter(MeterRegistry registry) {
return registry.counter("my.counter");
}
}

public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}

当我运行应用程序并在浏览器中调用http://localhost:8081/greeting时,它会崩溃并打印app context is NULL。如何获取应用程序上下文?我需要它来检索简单的计数器 bean。

最佳答案

tl;dr:你不需要上下文;有更好的方法。

ApplicationContextAware 是 Spring 旧版本的产物,在许多现在的标准功能可用之前。在现代 Spring 中,如果您需要 ApplicationContext,只需像注入(inject)任何其他 bean 一样注入(inject)它即可。但是,您几乎肯定不应该直接与它交互,特别是对于 getBean,它应该被替换为注入(inject)您所获得的任何内容。

一般来说,当您需要 Spring bean 时,您应该将其声明为构造函数参数。 (如果您有多个构造函数,则需要使用 @Autowired 注释一个构造函数,但如果只有一个构造函数,Spring 足够聪明,知道如何使用它。)如果您使用 Lombok,则可以使用@Value自动编写构造函数,Groovy和Kotlin也有类似的功能。

在此处展示的 Micrometer 的具体情况中,将单个指标声明为 Bean 的做法并不常见,因为它们是旨在应用于特定代码路径的细粒度工具。 (某些服务可能有 10 个单独的指标来跟踪各种可能的情况。)相反,您可以注入(inject) MeterRegistry 并选择您需要的计数器或其他指标作为构造函数的一部分。在这里,您的 Controller 类应该如下所示。 (我已经删除了重复的 AtomicLong,但如果有特定原因需要它,您可以将其添加回来,正如您所展示的那样。)

@RestController
public class GreetingController {

private static final Logger LOG = LoggerFactory.getLogger(GreetingController.class);

private static final String template = "Hello, %s!";

private final Counter counter;

public GreetingController(MeterRegistry meterRegistry) {
counter = meterRegistry.counter("my.counter");
}


@RequestMapping("/greeting")
public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {

counter.increment();
long count = (long) counter.count();

return new Greeting(count, String.format(template, name));
}
}

关于java - 如何在 Spring Boot 2 中检索应用程序上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56810020/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com