二十一、面向对象底层逻辑-scope作用域接口设计
一、引言:Bean生命周期的精密控制
在Spring框架中,Bean的作用域管理是容器体系的核心能力之一。Scope接口作为Spring作用域扩展机制的基石,赋予了开发者对Bean实例生命周期的原子级控制能力。通过该接口,我们既能使用Spring的内置作用域,也能实现自定义的实例管理策略,满足复杂业务场景的精细化控制需求。
二、接口定位与核心价值
1. 核心职责
-
实例生命周期管理:控制Bean的创建、获取和销毁时机
-
作用域策略扩展:支持自定义实例管理规则(如线程级、会话级作用域)
-
容器集成:与ApplicationContext深度整合,管理作用域上下文
-
资源释放控制:确保作用域结束时正确销毁相关资源
三、核心方法与实现解析
1. 接口定义
public interface Scope {// 获取作用域实例(核心方法)Object get(String name, ObjectFactory<?> objectFactory);// 移除指定实例@NullableObject remove(String name);// 注册销毁回调void registerDestructionCallback(String name, Runnable callback);// 解析上下文键(如会话ID)@NullableObject resolveContextualObject(String key);// 获取会话标识(用于作用域隔离)@NullableString getConversationId();
}
2. Spring内置实现
实现类 | 作用域 | 特点 | 典型应用场景 |
---|---|---|---|
SingletonScope | singleton | 默认作用域,单例模式 | 无状态服务、配置类 |
PrototypeScope | prototype | 每次获取新实例 | 有状态对象、线程不安全类 |
RequestScope | request | 请求级别作用域 | Web请求上下文数据存储 |
SessionScope | session | 会话级别作用域 | 用户会话数据管理 |
SimpleThreadScope | thread | 线程级别作用域(需手动注册) | 线程局部变量管理 |
四、自定义作用域实现指南
1. 实现步骤
步骤一:实现Scope接口
public class ClusterScope implements Scope {private final ConcurrentMap<String, Object> instances = new ConcurrentHashMap<>();@Overridepublic Object get(String name, ObjectFactory<?> objectFactory) {return instances.computeIfAbsent(name, k -> objectFactory.getObject());}@Overridepublic void registerDestructionCallback(String name, Runnable callback) {// 集群环境下向所有节点广播销毁事件ClusterEventPublisher.publishDestructionEvent(name, callback);}
}
步骤二:注册自定义作用域
@Configuration
public class ScopeConfig {@Beanpublic static CustomScopeConfigurer clusterScopeConfigurer() {CustomScopeConfigurer configurer = new CustomScopeConfigurer();configurer.addScope("cluster", new ClusterScope());return configurer;}
}
步骤三:使用自定义作用域
@Service
@Scope("cluster")
public class ClusterWideCache {// 集群范围内共享的缓存实例
}
五、高级应用场景
1. 分布式会话管理
public class DistributedSessionScope implements Scope {private final SessionStore sessionStore; // 连接Redis/Memcached等public Object get(String name, ObjectFactory<?> objectFactory) {String sessionId = getCurrentSessionId();return sessionStore.computeIfAbsent(sessionId, name, () -> objectFactory.getObject());}
}
2. 事务绑定作用域
public class TransactionScope implements Scope {public Object get(String name, ObjectFactory<?> objectFactory) {if (TransactionSynchronizationManager.isActualTransactionActive()) {// 事务内返回同一实例return TransactionResources.get(name, objectFactory);}return objectFactory.getObject(); // 非事务环境新实例}
}
3. 租户隔离实现
public class TenantScope implements Scope {public Object get(String name, ObjectFactory<?> objectFactory) {String tenantId = TenantContext.getCurrentTenant();return TenantIsolatedCache.get(tenantId, name, objectFactory);}
}
六、生产级最佳实践
1. 作用域代理配置
@Bean
@Scope(scopeName = "cluster", proxyMode = ScopedProxyMode.TARGET_CLASS)
public CacheService clusterCache() {return new RedisCacheService();
}
2. 生命周期监控
public class MonitoringScope implements Scope {private final Scope delegate;public Object get(String name, ObjectFactory<?> objectFactory) {long start = System.currentTimeMillis();Object instance = delegate.get(name, objectFactory);Metrics.recordGetTime(name, System.currentTimeMillis() - start);return instance;}
}
3. 资源泄漏防护
public class LeakDetectionScope implements Scope {private final Map<String, WeakReference<Object>> instances = Collections.synchronizedMap(new HashMap<>());public Object get(String name, ObjectFactory<?> objectFactory) {Object instance = objectFactory.getObject();instances.put(name, new WeakReference<>(instance));LeakDetector.monitor(instance);return instance;}
}
七、接口设计底层逻辑
1. 服务域对象
Scope属于服务域对象,以单实例服务于所有调用,加载后不可变并缓存在ConfigurableBeanFactory中。
2. 元数据对象
Scope接口中传入的String name属于元数据,描述了bean的名称,同时传入了ObjectFactory,它属于服务域对象。
3. 实体域对象
Scope接口返回的Object属于实体域对象
4. 单一职责
Strategy interface used by a {@link ConfigurableBeanFactory},
* representing a target scope to hold bean instances in.
* This allows for extending the BeanFactory's standard scopes
官方注释说明了该接口是一个ConfigurableBeanFactory所使用的策略接口,作用域内部持有bean实例,能够扩展beanfactory的标准作用域。
5. 扩展性
ConfigurableBeanFactory定义了registerScope方法,所以scope的扩展性通过注册的方式实现,允许扩展者在框架外围添加scope到内核。事实上,控制bean中@value自动刷新的RefreshScope就是通过postProcessor添加进去的。