Spring BeanFactory对于含有@RefreshScope注解的bean加载
Spring BeanFactory对于Bean的加载是大致分为三种的,第一种:单例bean,Scope为Singleton,第二种:多例bean,Scope为Prototype,然后就是第三种,除上述两类的都属于第三种,其中就有Scope为refresh的bean,即被@RefreshScope注解过的bean,BeanFactory对于Scope为refresh的bean的加载代码如下:
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
分析如下:
- 1.首先根据BeanDefinition获取scopeName,然后从Scope实例列表里面获取到相应的实例,针对@RefreshScope而言,scopeName为refresh,Scope实例为RefreshScope类型的实例
- 2.接下来通过Scope的get(String name, ObjectFactory<?> objectFactory)方法获取实例,如果获取不到将会通过传递的ObjectFactory工厂对象创建一个实例(创建的具体过程这里不赘述)
RefreshScope类详解
RefreshScope是继承的GenericScope的get(String name, ObjectFactory<?> objectFactory)方法,GenericScope中会为bean做一个简单的缓存,如下:
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
BeanLifecycleWrapper value = this.cache.put(name,
new BeanLifecycleWrapper(name, objectFactory));
this.locks.putIfAbsent(name, new ReentrantReadWriteLock());
try {
return value.getBean();
}
catch (RuntimeException e) {
this.errors.put(name, e);
throw e;
}
}
分析如下:
- 1.初始化一个管理bean生命周期的BeanLifecycleWrapper实例,如果不存在这个beanName的缓存的情况下会将这个BeanLifecycleWrapper实例放入BeanLifecycleWrapperCache缓存(其实这里有点缺陷,就是并不需要每次去初始化一个BeanLifecycleWrapper实例)
- 2.如果不存在这个beanName对应的读写锁,将会初始化一个ReentrantReadWriteLock放入locks这个map集合中
- 3.通过BeanLifecycleWrapper的getBean()方法获取bean
- 4.如果有异常,先统计异常然后再重新抛出去
BeanLifecycleWrapper的getBean()
public Object getBean() {
if (this.bean == null) {
synchronized (this.name) {
if (this.bean == null) {
this.bean = this.objectFactory.getObject();
}
}
}
return this.bean;
}
其实就是通过对象创建工厂ObjectFactory创建一个新的bean(这里的双重检查锁也有点问题,bean字段并没有用volatile声明,多线程创建的话即使有某个线程创建成功了,其他线程也感知不到)
由此可见,如果BeanLifecycleWrapperCache中关于beanName的缓存的BeanLifecycleWrapper实例不变的话,那么将一直获取的是上述过程创建的bean(BeanLifecycleWrapper没有提供公开的setBean方法,因此基本不用担心BeanLifecycleWrapper缓存的bean实例被重新设置为null)
RefreshScope的refresh与refreshAll
@ManagedOperation(description = "Dispose of the current instance of bean name "
+ "provided and force a refresh on next method execution.")
public boolean refresh(String name) {
if (!name.startsWith(SCOPED_TARGET_PREFIX)) {
// User wants to refresh the bean with this name but that isn't the one in the
// cache...
name = SCOPED_TARGET_PREFIX + name;
}
// Ensure lifecycle is finished if bean was disposable
if (super.destroy(name)) {
this.context.publishEvent(new RefreshScopeRefreshedEvent(name));
return true;
}
return false;
}
@ManagedOperation(description = "Dispose of the current instance of all beans "
+ "in this scope and force a refresh on next method execution.")
public void refreshAll() {
super.destroy();
this.context.publishEvent(new RefreshScopeRefreshedEvent());
}
分析如下:
- 1.refresh专门针对某一个bean的,在成功销毁之后发推送一个针对该bean的RefreshScopeRefreshedEvent事件
- 2.refreshAll会销毁所有Scope为refresh的bean,在销毁完成之后会推送一个RefreshScopeRefreshedEvent事件
refresh bean的销毁
单个销毁
protected boolean destroy(String name) {
BeanLifecycleWrapper wrapper = this.cache.remove(name);
if (wrapper != null) {
Lock lock = this.locks.get(wrapper.getName()).writeLock();
lock.lock();
try {
wrapper.destroy();
}
finally {
lock.unlock();
}
this.errors.remove(name);
return true;
}
return false;
}
分析如下:
- 1.从BeanLifecycleWrapperCache中移除针对该bean设置的缓存
- 2.如果存在该bean的缓存,先获取到读写锁,然后加锁并执行BeanLifecycleWrapper的destroy()方法,执行完成之后解锁,移除错误列表errors中该bean对应的错误信息
全部销毁
@Override
public void destroy() {
List<Throwable> errors = new ArrayList<Throwable>();
Collection<BeanLifecycleWrapper> wrappers = this.cache.clear();
for (BeanLifecycleWrapper wrapper : wrappers) {
try {
Lock lock = this.locks.get(wrapper.getName()).writeLock();
lock.lock();
try {
wrapper.destroy();
}
finally {
lock.unlock();
}
}
catch (RuntimeException e) {
errors.add(e);
}
}
if (!errors.isEmpty()) {
throw wrapIfNecessary(errors.get(0));
}
this.errors.clear();
}
跟单个销毁是差不多的过程,不赘述
BeanLifecycleWrapper之destroy()
public void destroy() {
if (this.callback == null) {
return;
}
synchronized (this.name) {
Runnable callback = this.callback;
if (callback != null) {
callback.run();
}
this.callback = null;
this.bean = null;
}
}
执行销毁方法,并将缓存的bean以及callback设置为null,下一次获取bean的话将会重新执行ObjectFactory的getObject()方法获取新的bean
注册销毁方法
// BeanLifecycleWrapper
public void setDestroyCallback(Runnable callback) {
this.callback = callback;
}
// GenericScope
@Override
public void registerDestructionCallback(String name, Runnable callback) {
BeanLifecycleWrapper value = this.cache.get(name);
if (value == null) {
return;
}
value.setDestroyCallback(callback);
}
// AbstractBeanFactory
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
在看到registerDisposableBeanIfNecessary这个方法时,相信看过之前写的一篇Spring bean销毁的文章的朋友会比较熟系,文章地址:Spring bean销毁的过程