Spring 实现自定义的 bean 作用域
- 实现 Scope 接口
- 调用 AbstractBeanFactory#registerScope 方法
- bean 配置的地方指定作用域,如 <bean scope=""> 或 @Scope("")
以下实现一个线程级别的 bean 的作用域
先看 Scope 接口的实现
/**
* 线程级别 scope
*
* @author ConstXiong
*/
public class ThreadLocalScope implements Scope {
public static final String SCOPE_NAME = "thread-local";
private static final ThreadLocal<Map<String, Object>> THREAD_LOCAL = new ThreadLocal<Map<String, Object>>() {
@Override
protected Map<String, Object> initialValue() {
return new HashMap<>();
}
};
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
Map<String, Object> map = THREAD_LOCAL.get();
Object object = map.get(name);
if (object == null) {
object = objectFactory.getObject();
map.put(name, object);
}
return object;
}
@Override
public Object remove(String name) {
return THREAD_LOCAL.get().remove(name);
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object resolveContextualObject(String key) {
return THREAD_LOCAL.get().remove(key);
}
@Override
public String getConversationId() {
return String.valueOf(Thread.currentThread().getId());
}
}
使用 ApplicationContextAware 接口获取 ApplicationContext,在其 BeanFactory 中注册 ThreadLocalScope
/**
* 注册 ThreadLocalScope
*
* @author ConstXiong
*/
@Component
public class ScopeRegister implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
WebApplicationContext context = (WebApplicationContext)applicationContext;
DefaultListableBeanFactory beanFactory = ((DefaultListableBeanFactory)context.getAutowireCapableBeanFactory());
beanFactory.registerScope(ThreadLocalScope.SCOPE_NAME, new ThreadLocalScope());
}
}
bean 配置与 controller
/**
* controller
*
* @author ConstXiong
*/
@Controller
public class IndexController {
@Autowired
private ApplicationContext context;
@RequestMapping("thread")
@ResponseBody
public String thread() {
User user = context.getBean("user", User.class);
return String.format("thread:%s, user:%s", Thread.currentThread().getId(), user);
}
@Bean
@Scope(ThreadLocalScope.SCOPE_NAME)
private static User user() {
return new User();
}
}
这样在页面请求 http://localhost:8080/thread,线程 id 不同,bean id 也不同
完整代码:023-spring-bean-custom-scope
【Java学习资源】整理推荐
- 自定义 Bean 作用域
- Bean 的作用域
- maven 集成 tomcat 以 jar 的方式打包 web 应用
- Spring 依赖注入与依赖查找来源的区别
- Spring 依赖注入的处理过程与 DependencyDescriptor 的说明
- Spring 各种 Aware 接口回调注入
- Spring Bean 生命周期内的 Exception 复现
- Spring 内建 Bean
- Spring Bean 的别名
- Spring Bean 未指定名称的命名规则
- Bean 何时被 GC
- Spring Bean 延迟加载
- ObjectFactory 与 BeanFactory 的区别
- Bean 销毁的方式与顺序
- Bean 初始化的方式与顺序
- Bean 的实例化方式
- Bean的注册方式
- 什么是 BeanDefinition?
- Spring IoC 容器启动时做了什么?
- BeanFactory 与 FactoryBean 的区别
- BeanFactory 与 ApplicationContext 的区别
- Spring IoC 依赖注入的实现方式
- Spring IoC 依赖注入(支持哪些数据类型?)
- Spring bean 依赖查找
- Spring-IoC
- Spring 的核心特性