1. 创建一个实现Scope接口的类
- 实现同一线程使用同一个bean,不同线程创建新的bean
package org.example.scope;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
public class CustomScope implements Scope {
private ThreadLocal local = new ThreadLocal();
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
if (local.get() != null) {
return local.get();
}else {
//调用createBean方法创建一个新的实例
Object object = objectFactory.getObject();
local.set(object);
return object;
}
}
@Override
public Object remove(String name) {
return null;
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
return null;
}
}
2. 创建一个实现BeanFactoryPostProcessor接口的类
- 将自定义的scope注册到容器中
3. 创建一个Scope类型的类
- 设置scope为fisherScope
package org.example.scope;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("fisherScope")
public class CustomScopeBean {
}
4. 测试方法
- 同一线程打印获取2次bean,打印查看hashcode是否一致
- 不同线程,查看hashcode是否不同
5. 源码分析
- 自定义scope的bean在doGetBean()内的实现方法
// 1.拿到scope名称,这里是fisherScope
String scopeName = mbd.getScope();
// 2.通过fisherScope拿到CustomScope类
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 3. 调用自己重写的get方法,如果是新的线程就是调到createBean()创建一个新的实例
// 如果是同一个线程,先从当前线程的ThreadLocal中拿实例,没有再去调createBean()
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}