如何使自动装配在配置 class 中工作?
How do I make Autowired work inside a Configuration class?
我正在尝试在 @Configuration class 中自动装配一个标记为 @Service
的属性 (myService),但我得到一个 NullPointer。
相反,如果我在非配置 classes 中自动装配 myService
,我没有问题。
这是我在自动装配时遇到问题的@Service:
package com.myapp.resources;
@Service
class MyService {
public List<String> getRoutingKeys() {
List<String> routingKeys;
//Do stuff
return routingKeys;
}
public String aMethod() {
return "hello";
}
}
这是我无法自动装配服务的 @Configuration class
package com.myapp.messaging;
import com.myapp.resources;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class RabbitConfiguration {
private List<String> routingKeys = writeRoutingKeys();
@Autowired
private MyService myService;
private List<String> writeRoutingKeys() {
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: true!!!
return myService.getRoutingKeys(); //here I get a NullPointer
}
//Methods with bean declarations for RabbitMQ
}
如果有帮助,这是我的主要class:
package com.myapp;
import com.myapp.resources;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import java.util.List;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext appContext = SpringApplication.run(Application.class, args);
MyService myService = (MyService) appContext.getBean(MyService.class);
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: false
//Do stuff
}
}
如果有帮助,这里有一个不同的 class(@RestController),我可以在其中自动连接服务
package com.myapp.resources;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@Autowired
private MyService myService;
@GetMapping("/endpoint")
public String myRestMethod() {
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: false
return myService.aMethod();
}
}
我也试过在配置中添加 @ComponentScan class,但我仍然得到一个 NullPointer
package com.myapp.messaging;
//list of imports...
@Configuration
@ComponentScan("com.myapp.demo")
public class RabbitConfiguration {
@Autowired
private MyService myService;
//...
}
我建议通过任何需要它的 @Bean
创建方法来注入服务:
@Bean
public MyBean create(MyService myService)
然后将服务传入writeRoutingKeys(MyService myService)
方法进行相应的处理。
根据文档:
@Configuration classes are processed quite early during the
initialization of the context and forcing a dependency to be injected
this way may lead to unexpected early initialization. Whenever
possible, resort to parameter-based injection as in the example above.
Spring 只会在实例化 bean 之后或实例化时注入依赖项(取决于是否使用构造函数注入)。但是,您现在在初始化 bean 之前发生的字段初始化期间访问依赖项 MyService
。因此,它无法在字段初始化期间访问 MyService
,因为它尚未注入。
您可以通过更改为使用构造函数注入并同时在构造函数中初始化 routingKeys
来简单地修复它:
@Configuration
public class RabbitConfiguration {
private List<String> routingKeys ;
private MyService myService;
@Autowired
public RabbitConfiguration(MyService myService){
this.myService = myService
this.routingKeys = writeRoutingKeys();
}
private List<String> writeRoutingKeys() {
return myService.getRoutingKeys();
}
}
或者简单地说:
@Autowired
public RabbitConfiguration(MyService myService){
this.myService = myService
this.routingKeys = myService.getRoutingKeys();
}
我正在尝试在 @Configuration class 中自动装配一个标记为 @Service
的属性 (myService),但我得到一个 NullPointer。
相反,如果我在非配置 classes 中自动装配 myService
,我没有问题。
这是我在自动装配时遇到问题的@Service:
package com.myapp.resources;
@Service
class MyService {
public List<String> getRoutingKeys() {
List<String> routingKeys;
//Do stuff
return routingKeys;
}
public String aMethod() {
return "hello";
}
}
这是我无法自动装配服务的 @Configuration class
package com.myapp.messaging;
import com.myapp.resources;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class RabbitConfiguration {
private List<String> routingKeys = writeRoutingKeys();
@Autowired
private MyService myService;
private List<String> writeRoutingKeys() {
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: true!!!
return myService.getRoutingKeys(); //here I get a NullPointer
}
//Methods with bean declarations for RabbitMQ
}
如果有帮助,这是我的主要class:
package com.myapp;
import com.myapp.resources;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import java.util.List;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext appContext = SpringApplication.run(Application.class, args);
MyService myService = (MyService) appContext.getBean(MyService.class);
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: false
//Do stuff
}
}
如果有帮助,这里有一个不同的 class(@RestController),我可以在其中自动连接服务
package com.myapp.resources;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@Autowired
private MyService myService;
@GetMapping("/endpoint")
public String myRestMethod() {
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: false
return myService.aMethod();
}
}
我也试过在配置中添加 @ComponentScan class,但我仍然得到一个 NullPointer
package com.myapp.messaging;
//list of imports...
@Configuration
@ComponentScan("com.myapp.demo")
public class RabbitConfiguration {
@Autowired
private MyService myService;
//...
}
我建议通过任何需要它的 @Bean
创建方法来注入服务:
@Bean
public MyBean create(MyService myService)
然后将服务传入writeRoutingKeys(MyService myService)
方法进行相应的处理。
根据文档:
@Configuration classes are processed quite early during the initialization of the context and forcing a dependency to be injected this way may lead to unexpected early initialization. Whenever possible, resort to parameter-based injection as in the example above.
Spring 只会在实例化 bean 之后或实例化时注入依赖项(取决于是否使用构造函数注入)。但是,您现在在初始化 bean 之前发生的字段初始化期间访问依赖项 MyService
。因此,它无法在字段初始化期间访问 MyService
,因为它尚未注入。
您可以通过更改为使用构造函数注入并同时在构造函数中初始化 routingKeys
来简单地修复它:
@Configuration
public class RabbitConfiguration {
private List<String> routingKeys ;
private MyService myService;
@Autowired
public RabbitConfiguration(MyService myService){
this.myService = myService
this.routingKeys = writeRoutingKeys();
}
private List<String> writeRoutingKeys() {
return myService.getRoutingKeys();
}
}
或者简单地说:
@Autowired
public RabbitConfiguration(MyService myService){
this.myService = myService
this.routingKeys = myService.getRoutingKeys();
}