如何在配置类中使自动装配工作?

时间:2019-08-19 14:12:12

标签: java spring spring-boot autowired

我正在尝试在@Configuration类中自动装配标记为@Service的属性(myService),但是我得到了一个N​​ullPointer。
相反,如果我将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类,在这里我无法自动连接服务

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
 }

如果有帮助,这是我的主班:

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

如果有帮助,这里是另一个类(@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();
    }
}

我也尝试在Configuration类中添加@ComponentScan,但是我仍然得到NullPointer

package com.myapp.messaging;

//list of imports...

@Configuration
@ComponentScan("com.myapp.demo")
public class RabbitConfiguration {
   @Autowired
   private MyService myService;

   //...
}

2 个答案:

答案 0 :(得分:0)

我建议通过任何需要它的@Bean创建方法来注入服务:

@Bean
public MyBean create(MyService myService)

,然后将该服务传递到writeRoutingKeys(MyService myService)方法中以进行相应处理。

每个文档:

  

@Configuration类在   上下文的初始化并强制注入依赖项   这种方式可能会导致意外的早期初始化。每当   如上例所示,可以使用基于参数的注入。

答案 1 :(得分:0)

Spring仅在实例化bean之后或实例化时注入依赖项(取决于是否使用构造函数注入)。但是,您现在正在字段初始化期间访问依赖项MyService,这在初始化bean之前发生。因此,由于尚未注入,它无法在字段初始化期间访问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();
}