反例 1: SpringContext 作为静态变量
UserController 和 SpringContextUtils 类没有依赖关系, SpringContextUtils.getApplication() 可能返回空。并且 Spring 非依赖关系的 Bean 之间的初始化顺序是不确定的,虽然可能当前初始化顺序恰好符合期望,但后续可能发生变化。
@Component
public class SpringContextUtils {
@Getter
private static ApplicationContext applicationContext;
public SpringContextUtils(ApplicationContext context) {
applicationContext = context;
}
}
@Component
public class UserController {
public void handle(){
MyService bean = SpringContextUtils.getApplicationContext().getBean(MyService.class);
}
}
反例 2: Switch 在 Spring Bean 中注册, 但通过静态方式读取
@Component
public class SwitchConfig {
@PostConstruct
public void init() {
SwitchManager.register("appName", MySwitch.class);
}
public static class MySwitch {
@AppSwitch(des = "config", level = Switch.Level.p1)
public static String config;
}
}
@Component
public class UserController{
public String getConfig(){
// UserController 和 SwitchConfig 类没有依赖关系, MySwitch.config 可能还没有初始化
return MySwitch.config;
}
}
通过 SpringBeanFactory 保证初始化顺序:
public class PreInitializer implements BeanFactoryPostProcessor, PriorityOrdered {
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
try {
SwitchManager.init(应用名, 开关类.class);
} catch (SwitchCenterException e) {
// 此处抛错最好阻断程序启动,避免开关读不到持久值引发问题
} catch (SwitchCenterError e) {
System.exit(1);
}
}
}
@Component
public class SpringContextUtilPostProcessor implements BeanFactoryPostProcessor, PriorityOrdered, ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
SpringContextUtils.setApplicationContext(applicationContext);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}