RefreshScope中ContextRefreshedEvent处理逻辑的两个技术疑问
RefreshScope中ContextRefreshedEvent处理逻辑的两个问题解答
在Spring Cloud的org.springframework.cloud.context.scope.refresh.RefreshScope中,处理ContextRefreshedEvent的逻辑如下:
@Override public void onApplicationEvent(ContextRefreshedEvent event) { start(event); } public void start(ContextRefreshedEvent event) { if (event.getApplicationContext() == this.context && this.eager && this.registry != null) { eagerlyInitialize(); } } private void eagerlyInitialize() { for (String name : this.context.getBeanDefinitionNames()) { BeanDefinition definition = this.registry.getBeanDefinition(name); if (this.getName().equals(definition.getScope()) && !definition.isLazyInit()) { Object bean = this.context.getBean(name); // question 1 if (bean != null) { // question 2 bean.getClass(); } } } }
问题1:调用getBean方法时,若Bean不存在会抛出异常,为何还要判断Bean是否为null?
Spring的getBean()方法多数场景下会在Bean不存在或初始化失败时抛出异常,但存在特殊场景会返回null:
- 当Bean是
FactoryBean类型时,如果其getObject()方法返回null,调用getBean(name)会直接返回null,而非抛出异常; - 极少数自定义BeanFactory或BeanPostProcessor的实现中,可能存在返回null的情况。
这里的null判断就是为了兼容这些边缘场景,避免后续调用bean.getClass()时出现NullPointerException。
问题2:执行bean.getClass()看似无实际意义,为何要添加该处理逻辑?
因为RefreshScope的Bean默认通过动态代理实现(CGLIB或JDK代理),调用getBean()返回的只是代理对象,真实的目标Bean此时可能还未完成初始化。
调用bean.getClass()会触发代理对象的方法调用逻辑:代理类会在第一次接收到方法调用(包括getClass())时,创建并初始化真实的目标Bean。这样就能实现eagerlyInitialize()方法的目的——提前初始化所有非懒加载的RefreshScope Bean,而非等到第一次业务调用时才触发初始化。
内容的提问来源于stack exchange,提问作者duanduan
相关产品推荐
相关产品推荐

