@Autowired @Service Bean имеет нулевое значение, хотя настроен правильно - PullRequest
1 голос
/ 27 мая 2019

Я получаю эту ошибку при запуске приложения на основе Spring Boot 2.1.4:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [test.services.AlmConnectivity]: Constructor threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:184) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1295) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    ... 22 common frames omitted
Caused by: java.lang.NullPointerException: null
    at test.services.AlmConnectivity.initProxyBean(AlmConnectivity.java:43) ~[classes/:na]
    at test.services.AlmConnectivity.<init>(AlmConnectivity.java:30) ~[classes/:na]

Упомянутая строка 43 начинается с proxy =:

@DependsOn({ "config", "cfg" })
private void initProxyBean() {
    System.err.println("Config: " + config);
    proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(config.getProxyHost(), config.getProxyPort()));
}

System.err печатает также ноль. Как видите, я пытался сигнализировать о зависимостях, используя @DependsOn.

Это (я думаю) другие соответствующие части класса:

@Service
public class AlmConnectivity {
    Logger log = LoggerFactory.getLogger(AlmConnectivity.class);

    @Autowired
    @Qualifier("config")
    Config config;

    private Proxy proxy;

    private OkHttpClient client;

    public AlmConnectivity() {
        initProxyBean();
        initClientBean(proxy);
    }

Поскольку я предпочитаю более короткие имена, я использовал @Qualifier, но даже если я пропущу это и возьму бин с его полным именем config, он не будет работать, а конфигурация останется нулевой.

Это класс конфигурации:

@Component
public class Config {

    @NotNull
    @NotEmpty
    @Value("${proxy.host}")
    private String proxyHost = "i.am.desparate";

    @NotNull
    @NotEmpty
    @Value("${proxy.port}")
    private int proxyPort = 8090;

    public String getProxyHost() {
        return proxyHost;
    }

    public int getProxyPort() {
        return proxyPort;
    }
}

Мой основной класс несет следующие аннотации:

@SpringBootApplication
@EnableScheduling
@Configuration
@ComponentScan
@EnableAutoConfiguration

(последние три были добавлены во время моих попыток запустить это)

Ответы [ 2 ]

2 голосов
/ 27 мая 2019

Возможно, вы захотите изменить свое поведение с вызова в конструкторе на

javax.annotation.PostConstruct

аннотированный метод:

@Service
public class AlmConnectivity {

    Logger log = LoggerFactory.getLogger(AlmConnectivity.class);

    @Autowired
    @Qualifier("config")
    Config config;

    private Proxy proxy;

    private OkHttpClient client;

    @PostConstruct
    private void initProxyBean() {
        System.err.println("Config: " + config);
        proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(config.getProxyHost(), config.getProxyPort()));
    }
}
1 голос
/ 27 мая 2019

Просто чтобы добавить информацию к ответу, предоставленному Smutje выше:

Конструкторы бинов предназначены для создания экземпляров бина.

Spring сначала вызывает конструктор Bean, и только после этого, когда есть экземпляр bean-компонента, вызывается логика Autowiring (Вы можете прочитать о постпроцессорах bean в Spring, чтобы понять, как именно они работают, внехотя область действия для этого вопроса).

После того, как логика автопроводки выполнена и все поля автопроводки введены, Spring вызывает метод, помеченный @PostConstruct.

Это место, где вы можете инициализировать свой код.

Так что одним из возможных ответов действительно является использование пост-конструктора bean-компонента.

Другим способом является прекращение использования FieldИнъекция в пользу Конструктора Инъекция:

@Service  
public class AlmConnectivity {

  @Autowired // optional annotation in modern spring if you have a single constructor
  public AlmConnectivity(@Qualifier("config") Config  config) {
       // here config is not null, so you can init proxy
  }
}
...