基本原理
详细流程
(1)@Scope注解的解析
@Scope注解可用于类和方法上
类上的@Scope解析,在ConfigurationClassPostProcessor中,解析componentScan的时候进行解析。
具体位置在:org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
// 解析scope
// 在解析的过程中会注册一个bd={scopedTarget.testService={scope="refresh", beanClass="TestService"}}
// 然后返回一个dbHolder={testService={scope="", beanClass="ScopedProxyFactoryBean"}}
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 然后把{testService={scope="", beanClass="ScopedProxyFactoryBean"}} 返回
beanDefinitions.add(definitionHolder);
方法上的@Scope解析,在解析完配置类后,注册@Bean和@Import的时候进行解析的。
具体位置是:org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
中
// 此处才把@Bean的方法和@Import 注册到BeanDefinitionMap中
// 方法上的@Scope解析
this.reader.loadBeanDefinitions(configClasses);
解析完成后,会注册两个bd
- testService={scope="", beanClass="ScopedProxyFactoryBean"}
- scopedTarget.testService={scope="refresh", beanClass="TestService"}
(2)RefreshAutoConfiguration
在spring-cloud-context项目下,spring.factories中
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.WritableEnvironmentEndpointAutoConfiguration
RefreshAutoConfiguration
- 定义了@Bean RefreshEventListener 监听ApplicationReadyEvent和RefreshEvent
- 定义了@Bean RefreshScope
RefreshScope继承GenericScope, 而GenericScope实现了BeanDefinitionRegistryPostProcessor,
GenericScope利用BeanDefinitionRegistryPostProcessor的LockedScopedProxyFactoryBean()方法,将ScopedProxyFactoryBean替换成LockedScopedProxyFactoryBean
利用BeanDefinitionRegistryPostProcessor或者BeanFactoryPostProcessor的postProcessBeanFactory()方法注册了scope的处理器:refresh=new RefreshScope();
beanFactory.registerScope(this.name, this);
(3)获取bean
bean = getBean("testService")
testService对应的bd是{scope="singleton", beanClass=LockedScopedProxyFactoryBean}
getBean("testService")实际上获取的是单实例:LockedScopedProxyFactoryBean实例,实例化时,会初始化属性scopedTargetSouce=new SimpleBeanTargetSource(),这个scopedTargetSource接下来会有很大的用处。
LockedScopedProxyFactoryBean继承ScopedProxyFactoryBean 并且实现了BeanFactoryAware,在实例化后会执行setBeanFactory(),先执行父类ScopedProxyFactoryBean的setBeanFactory(),在这个方法里,会创建一个代理proxyFactory,这个proxyFactory的targetSource就是上面的scopedTargetSource,然后利用proxyFactory创建TestService的代理proxy。
并添加一个advise:DelegatingIntroductionInterceptor。
截止执行LockedScopedProxyFactoryBean的setBeanFactory()里的后续代码,proxy.addAdvice(0, this),即上面添加的DelegatingIntroductionInterceptor被替换了,且将LockedScopedProxyFactoryBean自己作为拦截器。
到这里bean就获取成功了,就是上面创建的proxy。
(4)执行bean.XXmethod()
这里就会走到proxy的invoke()方法来,即LockedScopedProxyFactoryBean的invoke()方法,
方法里先从locks中获取对应的读写锁,然后加读锁。
接着执行:
return ReflectionUtils.invokeMethod(method, advised.getTargetSource().getTarget(), invocation.getArguments());
即利用反射,执行target的method方法,advised.getTargetSource就是上面的SimpleBeanTargetSource,即调用SimpleBeanTargetSource的getTarget()方法
public Object getTarget() throws Exception {
return this.getBeanFactory().getBean(this.getTargetBeanName());
}
即beanFactory.getBean(“scopedTarget.testService”)
scopedTarget.testService的bd={scope="refresh", beanClass="TestService"}
在beanFactory.getBean()的调用中,会根据bd的scope类型,利用scope的处理器获取相应的bean
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
scope="refresh",就不会走if和else if,走的最后的els
这里就回到了RefreshScope.get() --> GenericScope.get()
/**
* getBean()的时候,会调到这里来,
* @param name
* @param objectFactory
* @return
*/
@Override public Object get(String name, ObjectFactory<?> objectFactory) {
// 先保存到缓存中,这里的objectFactory就是上图中的createBean()
BeanLifecycleWrapper value = this.cache.put(name, new BeanLifecycleWrapper(name, objectFactory));
// 放置读写锁
this.locks.putIfAbsent(name, new ReentrantReadWriteLock());
try {
// 这里getBean(),实际上创建的是TestService
return value.getBean();
} catch (RuntimeException e) {
this.errors.put(name, e);
throw e;
}
}
BeanLifecycleWrapper.getBean()
public Object getBean() { if (this.bean == null) { synchronized (this.name) { if (this.bean == null) { this.bean = this.objectFactory.getObject(); } } } return this.bean; }
就是调用createBean()的流程了,创建完bean之后,不会往一级缓存中存放,因为scope=refresh不是单例模式。
到这里target即TestService的实例就创建完成了。接着就是反射调用target的xxmethod方法了。
(5)第二次调用bean.xxxMethod()
在未修改配置的情况下,第二次调用时,从cache中获取BeanLifecycleWrapper然后获取bean,就相当于直接从缓存中读取了。
(6)修改配置,产生RefreshEvent事件。
前面说了RefreshAutoConfiguration中定义了RefreshEventListener监听RefreshEvent事件,
在接收到RefreshEvent事件之后,会调用RefreshScope的refreshAll()方法,这个方法又调用了super.destroy()即GenericScope.destroy()
public void destroy() {
List<Throwable> errors = new ArrayList<Throwable>();
// 清空cache缓存
Collection<BeanLifecycleWrapper> wrappers = this.cache.clear();
// 逐个销毁wrapper
for (BeanLifecycleWrapper wrapper : wrappers) {
try {
// 加写锁
Lock lock = this.locks.get(wrapper.getName()).writeLock();
lock.lock();
try {
// 销毁wrapper(调用callback, bean=null)
wrapper.destroy();
} finally {
lock.unlock();
}
} catch (RuntimeException e) {
errors.add(e);
}
}
if (!errors.isEmpty()) {
throw wrapIfNecessary(errors.get(0));
}
this.errors.clear();
}
可以看到,情况了cache缓存,下次再有方法调用时,cache为空,就又会新建wrapper,新建bean