Spring @Component доступен до завершения @PostConstruct - PullRequest
0 голосов
/ 08 февраля 2019

Я использую Spring Boot 2.0.3 для REST-приложения.У меня странная ситуация.

У меня есть этот интерфейс:

public interface ConnectionPoolManager {

    public Connection getConnection(@NotNull String tenantId, boolean longTask);

    public DataSource getDataSource(@NotNull String tenantId, boolean longTask);
}

и его реализация:

@Component
@Profile({"prod"})
public class ConnectionPoolManagerImpl implements ConnectionPoolManager {
    private Logger log = LogManager.getLogger();

    private Map<String, DataSource> dataSourceMap = new ConcurrentHashMap<String, DataSource>();


    private Map<String, DataSource> dataSourceLongConnectionsMap = new ConcurrentHashMap<String, DataSource>();

    private Map<String, String> tenantDatabaseInstanceMap = new ConcurrentHashMap<String, String>();

    @Autowired
    private TenantRestClient tenantRestClient;

    @Autowired
    private PasswordEncrypt passwordEncrypt;

    @Autowired
    private Environment env;

    @Autowired
    private DataSource primaryDataSource;

    /**
     * At application startup we cache connection to all DB instances
     */
    @PostConstruct
    public void init() {
        try {
            log.info("Caching datasource connections...");
            Set<String> databaseIds = tenantRestClient.findDatabaseInstanceIds();
            //Creating datasource and caching them for later
            databaseIds.forEach(s -> getLocalCache(false).put(s, createDataSource(s, false)));
            databaseIds.forEach(s -> getLocalCache(true).put(s, createDataSource(s, true)));
            log.info("Cached {} datasources", dataSourceMap.size());
        } catch (Exception e) {
            log.warn("Error trying to cache datasources.", e);
        }
    }

В этом классе я вызываю tenantRestClient.findDatabaseInstanceIds() итам у меня проблема.

@Component
public class TenantRestClient {
    private Logger log = LogManager.getLogger();

    @Autowired
    private RestTemplateBuilder restTemplateBuilder;

    private RestTemplate restTemplate;

    @PostConstruct
    public void init() {
        log.debug("------------INIT--------");
        restTemplate = restTemplateBuilder.build();
        log.debug("Post construct {} - {}", restTemplateBuilder, restTemplate);
        log.debug("------------INIT COMPLETED --------");
    }

  public Set<String> findDatabaseInstanceIds() {
           //my logic here

            ResponseEntity<Set<String>> response = restTemplate.exchange(uriBuilder.toUriString(), HttpMethod.GET, entity, new ParameterizedTypeReference<Set<String>>() {
            });

        }
    }

На самом деле метод findDatabaseInstanceIds () вызывается до вызова init ().Конечно, тогда у меня есть NullPointerException, потому что restTemplate имеет значение null.Как это возможно, бин tenantRestClient готов и метод может быть вызван до вызова метода init ()?

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Здесь вы можете воспользоваться аннотацией @DependsOn, которая позволит вам управлять порядком создания компонента

spring @ DependsOn

Вы можете пометить класс зависимого компонента, т. Е.ConnectionPoolManagerImpl с @ DependsOn

0 голосов
/ 08 февраля 2019

Вам необходимо создать класс Configuration с компонентом RestTemplate и автоматически связать его с вашим классом.

@Configuration
public class Config



@Bean
public RestTemplate restTemplate(){
  return restTemplateBuilder.build();

}

Это создаст компонент restTemplate для вашего проекта.Если вам нужно более одного RestTemplate, посмотрите на @ Qualifier.
Теперь вы можете автоматически подключить RestTemplate в своем классе.Нет необходимости в PostConstruct

@Component
public class TenantRestClient {
    private Logger log = LogManager.getLogger();

    @Autowired
    private RestTemplate restTemplate;

    public Set<String> findDatabaseInstanceIds() {
           //my logic here

            ResponseEntity<Set<String>> response = restTemplate.exchange(uriBuilder.toUriString(), HttpMethod.GET, entity, new ParameterizedTypeReference<Set<String>>() {
            });

        }
    }

...