项目集成了es,在项目中写了一个ElasticSearchClientConfig类,需要该类中创建RestHighLevelClient的实例对象。需要配置es的ip地址和port端口号,但是不能在代码中写死,这样就不够灵活和优雅了,于是我在PropertiesConfig类中添加了es相关的属性,并且将对应的值配置到了nacos配置中心上,通过@Value来获取对应的值,这样就会灵活优雅很多。
当我将代码修改后,重启服务后,发现获取不到对应的值。
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
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")));
}
}
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姿势不对的问题。
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配置中心的值。
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注释添加一个初始化方法来获取值。发现是可以获取到的。
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注解好多人以为是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;