[英]Why am I not able to get my Bean definition available in my Spring context with Spring Boot?
I'm feeling stupid to ask this, but I can't understand where I'm wrong with my code.问这个我感觉很愚蠢,但我不明白我的代码哪里错了。
The context is:上下文是:
The problem is:问题是:
Now the details:现在细节:
My SpringBootApplication:我的 SpringBoot 应用程序:
@SpringBootApplication
public class HbbTVApplication {
public static void main(String[] args) {
SpringApplication.run(HbbTVApplication.class, args);
}
}
My @Configuration class:我的@配置 class:
@Configuration
@Profile(value = { "dev", "int", "pre", "pro" })
public class StandaloneFrontalConfig extends WebMvcConfigurerAdapter {
@Value("${kafka.bootstrap-servers}")
private String bootstrapServers;
@Bean
public Map<String, Object> producerConfigs() {
Map<String, Object> props = new HashMap<>();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
return props;
}
@Bean
public ProducerFactory<String, String> producerFactory() {
return new DefaultKafkaProducerFactory<>(producerConfigs());
}
@Bean
public KafkaTemplate<String, String> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/standalone/");
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*");
}
};
}
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
@Bean
public Security securityManager() {
return new Security();
}
@Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public KngAflow getTechnicalCookie() {
return new KngAflow();
}
@Bean
public EmbeddedServletContainerCustomizer customizer() {
return new EmbeddedServletContainerCustomizer() {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof JettyEmbeddedServletContainerFactory) {
customizeJetty((JettyEmbeddedServletContainerFactory) container);
}
}
private void customizeJetty(JettyEmbeddedServletContainerFactory jetty) {
jetty.addServerCustomizers(new JettyServerCustomizer() {
@Override
public void customize(Server server) {
for (Connector connector : server.getConnectors()) {
if (connector instanceof ServerConnector) {
HttpConnectionFactory connectionFactory = ((ServerConnector) connector)
.getConnectionFactory(HttpConnectionFactory.class);
connectionFactory.getHttpConfiguration().setCookieCompliance(CookieCompliance.RFC2965);
}
}
}
});
}
};
}
}
My @Service:我的@服务:
@Service
public class CookieService implements services.CookieService, InitializingBean {
/**
* Serializable
*/
private static final long serialVersionUID = -1997257884335775587L;
@Autowired
ApplicationContext app;
@Override
public Cookie createTechnicalCookie() {
return new Cookie(app.getBean(KngAflow.class), null);
}
@Override
public void afterPropertiesSet() throws Exception {
if (app != null) {
for (String bean : app.getBeanDefinitionNames()) {
System.out.println("Bean: " + bean);
}
}
}
}
And the "non defined" bean:和“未定义”的bean:
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties({ "security", "maxAge", "domain", "updated" })
public class KngAflow implements Serializable, InitializingBean {
@JsonProperty(value = "did")
private String did;
@JsonProperty(value = "checksum")
private String checksum;
@Autowired
private Security security;
private Integer maxAge;
private String domain;
private boolean updated = false;
public KngAflow() {
domain = ".mydomain.com";
}
@Override
public void afterPropertiesSet() throws Exception {
did = UUID.randomUUID().toString();
maxAge = 365 * 24 * 60 * 60;
checksum = security.encrypt(did + security.md5(did));
}
}
NB: Classes are not complete, and there are more classes in my project.注意:课程不完整,我的项目中还有更多课程。 I only put what I saw as relevant information.
我只把我看到的作为相关信息。 If something else is needed, just ask me please.
如果需要其他东西,请问我。 By the way, all the endpoints are defined into a unique @Controller class, and all the endpoints are working except those needing the getTechCookie @Bean.
顺便说一句,所有端点都定义为一个唯一的@Controller class,除了需要getTechCookie @Bean 的端点之外,所有端点都在工作。
So, my problem occurs in runtime execution.所以,我的问题发生在运行时执行中。 When I start my Spring Boot app, Jetty is started and listening on the configured port.
当我启动我的 Spring Boot 应用程序时,Jetty 启动并侦听配置的端口。 Nevertheless, if you look at the CookieService @Service, I'm listing all the bean names defined in the autowired context and my getTechnicalCookie (aka KngAflow) @Bean is missing.
不过,如果您查看 CookieService @Service,我会列出自动装配上下文中定义的所有 bean 名称,而我的 getTechnicalCookie(又名 KngAflow)@Bean 丢失了。 I can't understand why.
我不明白为什么。
Of course, when I invoke my @controller to execute my @Service code, the NoSuchBeanDefinitionException is thrown executing the line app.getBean(KngAflow.class).当然,当我调用 @controller 来执行 @Service 代码时,会在执行 app.getBean(KngAflow.class) 行时抛出 NoSuchBeanDefinitionException。
I tried to use a bean name instead of bean type, no change.我尝试使用 bean 名称而不是 bean 类型,没有变化。 For testing purpose (as it doesn't make sense from a logical point of view), I defined my bean getTechCookie @Bean as a Singleton scoped bean, and the name is still missing from the ApplicationContext.
出于测试目的(因为从逻辑角度来看它没有意义),我将我的 bean getTechCookie @Bean 定义为 Singleton 范围的 bean,并且 ApplicationContext 中仍然缺少该名称。
And the last but not least thing is: Everything works fine with Eclipse!最后但并非最不重要的是:Eclipse 一切正常!
I mean, all my devs are done using Eclipse IDE.我的意思是,我所有的开发人员都是使用 Eclipse IDE 完成的。 My Spring Boot app is built with Maven and executing it inside Eclipse works correctly (and my getTechCookie Bean is defined and listed).
我的 Spring 引导应用程序是用 Maven 构建的,并在 Z32F7222026696F30787889196F30787889194DEE83E5Z 中执行它可以正常工作(并且我的 getTechCookie Bean 已定义并列出)。
When I package my app using the Maven Spring Boot plugin and execute it using java -jar, my getTechCookie (KngAflow.class) bean is missing. When I package my app using the Maven Spring Boot plugin and execute it using java -jar, my getTechCookie (KngAflow.class) bean is missing. Nevertheless, this class is present inside the jar.
然而,这个 class 存在于 jar 内部。
Spring parameters to launch the spring boot app are spring default values (port 8080, no SSL, ...) and the active.profiles are always between dev, int, pre or pro (those defined in my @Configuration class) Spring parameters to launch the spring boot app are spring default values (port 8080, no SSL, ...) and the active.profiles are always between dev, int, pre or pro (those defined in my @Configuration class)
What am I doing wrong?我究竟做错了什么?
Thanks!谢谢!
If it helps, I add my POM definition:如果有帮助,我添加我的 POM 定义:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>com.mydomain.bigdata</groupId>
<artifactId>mybigapp</artifactId>
<version>1.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*</include>
<include>application.yml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
EDIT: I changed my @Service class to "force" spring to accept my class as a prototype bean, and it works.编辑:我将我的@Service class 更改为“强制” spring 以接受我的 class 作为原型 bean,并且它可以工作。 It's very ugly but it works.
它非常难看,但它有效。 But if someone could help me to find what's wrong, I don't like this workaround:
但是,如果有人可以帮助我找出问题所在,我不喜欢这种解决方法:
@Override
public void afterPropertiesSet() throws Exception {
if (!context.containsBeanDefinition(KngAflow.class.getName()))
context.registerBeanDefinition(KngAflow.class.getName(),
BeanDefinitionBuilder.genericBeanDefinition(KngAflow.class).setScope("prototype").getBeanDefinition());
}
I made a following simple application to reproduce issue.我做了一个以下简单的应用程序来重现问题。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
run(Application.class, args);
}
}
@Configuration
@Profile("dev")
public class BeanConfiguration {
@Bean
@Scope(scopeName = SCOPE_PROTOTYPE)
public PrototypeBean prototypeBean() {
return new PrototypeBean();
}
}
public class PrototypeBean {}
@Service
@Slf4j
public class SingletonBean implements InitializingBean {
@Autowired
private ApplicationContext context;
public PrototypeBean getPrototypeBean() {
return context.getBean(PrototypeBean.class);
}
@Override
public void afterPropertiesSet() throws Exception {
for (String name : context.getBeanDefinitionNames()) {
Class<?> c = context.getBean(name).getClass();
log.debug("===> Name: {}, Type = {}", name, c.getTypeName());
}
}
}
@RestController
@RequestMapping("/bean")
public class BeanRestController {
@Autowired
private SingletonBean singletonBean;
@GetMapping("/name")
public String getName() {
return singletonBean.getPrototypeBean().getClass().getName();
}
}
When I execute application with -Dspring.profiles.active=dev setting当我使用-Dspring.profiles.active=dev设置执行应用程序时
Then I see in the log without no issue and REST endpoint gives back response properly:然后我在日志中看到没有问题,并且 REST 端点正确返回响应:
===> Name: prototypeBean, Type = PrototypeBean
But if I execute application without profile setting但是如果我在没有配置文件设置的情况下执行应用程序
Then I see error in the log and REST endpoint raise exception:然后我在日志中看到错误,并且 REST 端点引发异常:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'PrototypeBean' available
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.