@RefreshScope
今天正好学习到了使用nacos
作为配置中心,同时在配置的过程中也遇到了一些问题。
我们都知道配置要使用bootstrap.yml
,当我使用application.yml
进行配置的时候(同样以@Value
去取值),还是以bootastrap.yml
为准,这引发了我的好奇,第一个猜想即它使用了代理。
我们点开@RefrshScope
,那么也证明了这个结论:
@Scope("refresh")
public @interface RefreshScope {
/**
* @see Scope#proxyMode()
*/
ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}
下面对其流程做出解析。先来看看@Scope
吧
一、@Scope
我们平常所使用的@scope
都为singleton
或是prototype
,这两个是spring
硬编码的
但除了@scope
之外,我们还有Scope
接口,用于我们实现我们的自定义逻辑。因为作为spring的扩展点,它为我们提供了几个方法:
public interface Scope {
//得到Bean实例,通过objectFactory,可生成我们的对象,就像是mybatis一样,把我们的mapper解析为mapperFactoryBean
Object get(String name, ObjectFactory<?> objectFactory);
//销毁Bean
Object remove(String name);
//为指定名称的Bean注册销毁时的回调函数
void registerDestructionCallback(String name, Runnable callback);
Object resolveContextualObject(String key);
String getConversationId();
}
它实际上会自动给我们注入一些它自定义的Scope
也就是在我们的初始化阶段,会在beanFactory
中注册多个Scope
实例。如:
String SCOPE_REQUEST = "request";
String SCOPE_SESSION = "session";
String SCOPE_APPLICATION = "application";
String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
....
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
来看下RequestScope
,它其实就是Scope
的实现类
那么我们怎么获取的呢,肯定是在getBean->doGetBean
中。我们可以看见它会对scope
进行判断,应证了我们的之前的结论,默认的除了singleton
和prototye
之外,还有我们自己实现的,它会进行判断。
protected <T> T doGetBean() {
...
if (mbd.isSingleton()) {
}
else if (mbd.isPrototype()) {
}
//在这里
else {
//从我们已经解析出的bd中拿到scope
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get