关注小程序 找一找教程网-随时随地学编程

Java教程

java 静态代码块和spring @value等注解注入顺序

今天在进行配置抽取的时候,遇到一个问题通过@Value方法注入属性一直注入不进去。

引用yml配置文件的时候,因为用到了继承的静态代码块。类与类有继承关系的静态代码块是先执行父类静态代码块再执行子类静态代码块,这个问题不用说。

今天探索的是与spring相关的执行顺序

我在项目启动的时候需要去加载部分配置文件,这些配置文件的信息在子类的静态代码块需要使用的。跑项目的时候子类引用父类的属性一直报空指针。
 

package com.pinyu.system.utils;
 
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.Map;
 
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.Yaml;
 
import com.pinyu.system.web.controller.AppInfoController;
 

@Component
@SpringBootConfiguration
@PropertySource("classpath:application.yml")
public class YmlPropertiesUtils {
	
 
	@Value("${spring.profiles.active}")
	protected static String profilesActive;
 
	public static String getProfilesActive() {
		return profilesActive;
	}
	
}

子类实现

public class QuartzPropertiesUtils extends YmlPropertiesUtils {
 
	private static Properties quartzProperties;
	
	private static ClassPathResource quartzClassPathResource;
 
	static {
		try {
			if (profilesActive.equals(GlobalConstants.PROFILE_ACTIVE_DEV)) {
				quartzClassPathResource = new ClassPathResource("/quartz.properties");
			} else if(profilesActive.equals(GlobalConstants.PROFILE_ACTIVE_TEST)){
				quartzClassPathResource = new ClassPathResource("/test/quartz-test.properties");
			}
			quartzProperties = PropertiesLoaderUtils.loadProperties(quartzClassPathResource);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
 
	public static Properties getQuartzProperties() {
		return quartzProperties;
	}
 
	public static ClassPathResource getQuartzClassPathResource() {
		return quartzClassPathResource;
	}
}

在用到profilesActive这个的时候,一直是null。于是去研究了相关执行的顺序。

java static 静态代码块是最先执行的,然后再是spring 相关注入。这样按照上面的思路是获取不到profilesActive值得。因为静态代码块先加载,项目启动就会报错。

于是把父类也用静态代码块来进行获取,子类在父类静态代码块后执行,自然可以获取到。问题解决。

代码如下:

public class YmlPropertiesUtils {
	
	private static Logger logger = LogManager.getLogger(YmlPropertiesUtils.class);
 
//	@Value("${spring.profiles.active}")
	protected static String profilesActive;
 
	public static String getProfilesActive() {
		return profilesActive;
	}
 
	static{
		Yaml yaml = new Yaml();
        URL url = YmlPropertiesUtils.class.getClassLoader().getResource("application.yml");
        if (url != null) {
            //获取application.yaml文件中的配置数据,然后转换为obj,
			try {
//				Object obj= yaml.load(new FileInputStream(url.getFile()));
				Map map =(Map)yaml.load(new FileInputStream(url.getFile()));
				Map spring =(Map)map.get("spring");
				Map profiles =(Map)spring.get("profiles");
				profilesActive =(String) profiles.get("active");
			} catch (FileNotFoundException e) {
				e.printStackTrace();
				logger.info("配置初始化错误");
			}
        }
	}
}

主要记录一个知识点,java静态代码块和spring 注解执行的顺序
原文链接:https://blog.csdn.net/ypp91zr/article/details/84954395