前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >@Configuration 相关依赖注入问题

@Configuration 相关依赖注入问题

作者头像
用户8889406
发布2023-03-05 15:32:15
7450
发布2023-03-05 15:32:15
举报
文章被收录于专栏:小呙同学

出现的问题

问题的原因

项目集成了es,在项目中写了一个ElasticSearchClientConfig类,需要该类中创建RestHighLevelClient的实例对象。需要配置es的ip地址和port端口号,但是不能在代码中写死,这样就不够灵活和优雅了,于是我在PropertiesConfig类中添加了es相关的属性,并且将对应的值配置到了nacos配置中心上,通过@Value来获取对应的值,这样就会灵活优雅很多。

当我将代码修改后,重启服务后,发现获取不到对应的值。

代码语言:javascript
复制
import com.shlz.common.utils.PropertiesConfig;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import javax.annotation.PostConstruct;

/**
 * ElasticSearch客户端配置
 *
 * @author xGuo
 * @date 2022/07/19
 */
@Configuration
public class ElasticSearchClientConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient() {

        System.out.println("ElasticSearchClientConfig 获取属性值...");
        System.out.println(PropertiesConfig.ES_IP);
        System.out.println(PropertiesConfig.ES_PORT);
        System.out.println("ElasticSearchClientConfig 获取属性值结束...");
        return new RestHighLevelClient(
                RestClient.builder(new HttpHost(PropertiesConfig.ES_IP, 
                         PropertiesConfig.ES_PORT, "http")));
    }
}

控制台打印

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.RestHighLevelClient]: Factory method ‘restHighLevelClient’ threw exception; nested exception is java.lang.NullPointerException at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) … 35 common frames omitted

Caused by: java.lang.NullPointerException: null at com.shlz.common.config.ElasticSearchClientConfig.restHighLevelClient(ElasticSearchClientConfig.java:53) ====> ** 就是 return new RestHighLevelClient(…) 这行代码 ** at com.shlz.common.config.ElasticSearchClientConfig

restHighLevelClient1(<generated>)atcom.shlz.common.config.ElasticSearchClientConfig1(<generated>) at com.shlz.common.config.ElasticSearchClientConfig1(<generated>)atcom.shlz.common.config.ElasticSearchClientConfigEnhancerBySpringCGLIBEnhancerBySpringCGLIBEnhancerBySpringCGLIB3124811c3124811c3124811cFastClassBySpringCGLIBFastClassBySpringCGLIBFastClassBySpringCGLIBa8645581.invoke(<generated>)atorg.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)atorg.springframework.context.annotation.ConfigurationClassEnhancera8645581.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) at org.springframework.context.annotation.ConfigurationClassEnhancera8645581.invoke(<generated>)atorg.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)atorg.springframework.context.annotation.ConfigurationClassEnhancerBeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) at com.shlz.common.config.ElasticSearchClientConfig

相关代码

ElasticSearchClientConfig(es客户端配置类)
代码语言:javascript
复制
import com.shlz.common.utils.PropertiesConfig;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import javax.annotation.PostConstruct;

/**
 * ElasticSearch客户端配置
 *
 * @author xGuo
 * @date 2022/07/19
 */
@Configuration
public class ElasticSearchClientConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        return new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1", 9270, "http")));
    }
}
PropertiesConfig(属性配置类)
代码语言:javascript
复制
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class PropertiesConfig {
  	
    public static String ES_IP;

    public static Integer ES_PORT;


    @Value("${es.ip}")
    public void setEsIp(String esIp) {
        ES_IP = esIp;
    }

    @Value("${es.port}")
    public void setEsPort(Integer esPort) {
        ES_PORT = esPort;
    }
}

解决方式

原来我以为是修饰了@Configuration类无法引用另外一个修饰了@Configuration类中的属性,后面发现只是使用static姿势不对的问题。

尝试处理一:

代码语言:javascript
复制
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class PropertiesConfig {
  
  	@Value("${es.ip}")
    public  String ES_IP;
  
    @Value("${es.port}")
    public  Integer ES_PORT;
}

发现直接在ElasticSearchClientConfig中进行依赖注入,然后调用属性值,是可以获取到nacos配置中心的值。

代码语言:javascript
复制
import com.shlz.common.utils.PropertiesConfig;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * ElasticSearch客户端配置
 *
 * @author xGuo
 * @date 2022/07/19
 */
@Configuration
public class ElasticSearchClientConfig {

    @Autowired
    PropertiesConfig propertiesConfig;

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        return new RestHighLevelClient(
                RestClient.builder(new HttpHost(propertiesConfig.ES_IP, propertiesConfig.ES_PORT, "http")));
    }
}

尝试处理二:

PropertiesConfig类不做改动,在ElasticSearchClientConfig做处理,使用@PostConstruct注释添加一个初始化方法来获取值。发现是可以获取到的。

代码语言:javascript
复制
import com.shlz.common.utils.PropertiesConfig;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * ElasticSearch客户端配置
 *
 * @author xGuo
 * @date 2022/07/19
 */
@Configuration
public class ElasticSearchClientConfig {
    @Autowired
    PropertiesConfig propertiesConfig;
    
    private static String ip;
    private static Integer port;
    
    @PostConstruct
    public void init(){
        ip = PropertiesConfig.ES_IP;
        port = PropertiesConfig.ES_PORT;
    }

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        return new RestHighLevelClient(
                RestClient.builder(new HttpHost(ip,port, "http")));
    }
}
@PostConstruct详解

@PostConstruct注解好多人以为是Spring提供的。其实是Java自己的注解。 Java中该注解的说明:@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。 通常我们会是在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序: Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法) 应用:在静态方法中调用依赖注入的Bean中的方法。

但是!

当我发现我第一次尝试处理的时候(尝试处理一)写的依赖注入代码没有注释掉,所以我在想到底是@PostConstruct起了效果还是@Autowired起了效果?

@Autowired PropertiesConfig propertiesConfig;

于是,我注释掉了@Autowired的代码,再次重启服务,发现@PostConstruct修饰的init()方法也无法获取到值。

当我加上@Autowired的代码,再次重启服务,发现的确是又能获取到值了。

于是我干脆干掉了@PostConstruct修饰的init()方法,保留@Autowired的代码,发现依旧能够获取到值。

原因:@PostConstruct注解修饰的方法在整个Bean初始化中的执行顺序:

Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)

结论

当在@Bean中引用其他static修饰的属性的时候,需要进行依赖注入。

@Autowired PropertiesConfig propertiesConfig;

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 出现的问题
    • 问题的原因
      • 控制台打印
        • 相关代码
          • ElasticSearchClientConfig(es客户端配置类)
          • PropertiesConfig(属性配置类)
      • 解决方式
        • 尝试处理一:
          • 尝试处理二:
            • @PostConstruct详解
            • 但是!
        • 结论
        相关产品与服务
        Elasticsearch Service
        腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档