很多资料都说@Configuration 优先加载,@Service后加载,如下图:
本来也是以为 @Configuration 优先加载于 @Service ,那参数处理放在@Configuration注入完后,@service构建时就可以拿来用的,在我在IDEA的调试时下断点验证过。但在正式环境跑项目时并不是这样的。
先看原代码:
带@Configuration注解的配置参数代码如下:
@Configuration
public class SysParamApi {/*** 是否调试模式*/public static boolean is_debug=true;@Value("${sys-param.sys.is_debug}")public void setIs_debug(String is_debug) {SysParamApi.is_debug = "Y".equals(is_debug);System.out.println("是否调试模式:"+SysParamApi.is_debug);}}
带@Service业务类,有两个地方在使用这个参数。上面的@Configuration参数,代码如下:
@Service
public class PushStatusServiceImpl {private static final Logger logger = LogManager.getLogger(PushStatusServiceImpl.class);//调试时设置falseboolean isRun=true;@PostConstructpublic void init() {int cpuCount = Runtime.getRuntime().availableProcessors();System.out.println("start RedisStatusProcess > cpus=" + cpuCount);if(!SysParamApi.is_debug) {//业务处理logger.info("=========================== start rev pole status -> "+isRun);processOrderImport();}else{logger.info("xxxxxxxxxxxxxxxxxx start rev status -> Fail");}}
}@Service
public class PushOrderServiceImpl {private static final Logger logger = LogManager.getLogger(PushOrderServiceImpl.class);@PostConstructpublic void init() {int cpuCount = Runtime.getRuntime().availableProcessors();System.out.println("start RedisOrderProcess > cpus=" + cpuCount);//调试时设置falseif(!SysParamApi.is_debug){logger.info("=========================== start rev order -> "+isRun);processOrderImport(cpuCount);}else{logger.info("xxxxxxxxxxxxxxxxxx start rev order -> Fail");}}boolean isRun=true;
}
上面的代码在IDEA调试器执行时,确实是加载 @Configuration 执行打印是否调试模式这行 后加载@Service并执行init()方法,此时拿到SysParamApi.is_debug值 是注入后的值 。这也是大家认可。
在正式服务器发布后就翻车了,在不改上面任何代码及配置的情况下,执行的效果是:
第一次执行时:
发现先加载执行 @Service -> @Service -> @Configuration
第二次执行时:
发现先加载执行@Service -> @Configuration -> @Service
由于是正式服务器不能尝试多次,上面两次验证加载是随机的。
解决加载参数需要用到@PostConstruct注解,再修改代码如下:
@Service
public class PushOrderServiceImpl {private static final Logger logger = LogManager.getLogger(PushOrderServiceImpl.class);@Value("${sys-param.sys.is_debug}")public void setIs_debug(String is_debug) {SysParamApi.is_debug = "Y".equals(is_debug);System.out.println("是否调试模式:"+SysParamApi.is_debug);}@PostConstructpublic void init() {int cpuCount = Runtime.getRuntime().availableProcessors();System.out.println("start RedisOrderProcess > cpus=" + cpuCount);//调试时设置falseif(!SysParamApi.is_debug){logger.info("=========================== start rev order -> "+isRun);processOrderImport(cpuCount);}else{logger.info("xxxxxxxxxxxxxxxxxx start rev order -> Fail");}}boolean isRun=true;
}
说明:@PostConstruct注解的作用是本类加载完所有的参数(包含了流入参数),再执行。
生产环境测试验证:
上面测试生产环境参数:
操作系统:CentOS Linux release 8.1.1911
jdk环境:
openjdk version "1.8.0_275"
OpenJDK Runtime Environment (build 1.8.0_275-b01)
OpenJDK 64-Bit Server VM (build 25.275-b01, mixed mode)