🎯 目标: 设计线程安全、层次化的上下文管理系统,支持数据共享和隔离
🤔 为什么需要上下文管理?
在流程编排中,上下文是数据流转的核心:
- 📊 数据共享: 步骤之间需要传递和共享数据
- 🔒 数据隔离: 并行执行时需要隔离不同分支的数据
- 🌳 层次结构: 支持父子上下文的继承关系
- 💾 持久化: 支持上下文的序列化和恢复
- 🔍 监控追踪: 记录数据变更历史和访问轨迹
🏗️ 上下文架构设计
graph TB
subgraph "FlowContext 接口层 🎯"
A1[FlowContext]
A2[ReadOnlyFlowContext]
A3[MutableFlowContext]
end
subgraph "核心实现层 🔧"
B1[DefaultFlowContext]
B2[HierarchicalFlowContext]
B3[ThreadSafeFlowContext]
end
subgraph "扩展功能层 🚀"
C1[SerializableFlowContext]
C2[MonitoringFlowContext]
C3[CachingFlowContext]
end
subgraph "工具层 🛠️"
D1[ContextSerializer]
D2[ContextValidator]
D3[ContextMonitor]
end
A1 --> A2
A1 --> A3
A2 --> B1
A3 --> B1
B1 --> B2
B1 --> B3
B3 --> C1
B3 --> C2
B3 --> C3
C1 --> D1
C2 --> D3
C3 --> D2
🎯 FlowContext接口设计
java
/**
* 流程执行上下文接口
* 提供数据存储、检索和管理功能
*/
public interface FlowContext {
/**
* 存储数据
* @param key 键
* @param value 值
* @return 之前的值(如果存在)
*/
Object put(String key, Object value);
/**
* 获取数据
* @param key 键
* @return 值,如果不存在返回null
*/
Object get(String key);
/**
* 获取数据,如果不存在返回默认值
* @param key 键
* @param defaultValue 默认值
* @return 值或默认值
*/
<T> T get(String key, T defaultValue);
/**
* 获取指定类型的数据
* @param key 键
* @param type 期望的类型
* @return 转换后的值
* @throws ClassCastException 如果类型不匹配
*/
<T> T get(String key, Class<T> type);
/**
* 检查是否包含指定键
* @param key 键
* @return 是否包含
*/
boolean containsKey(String key);
/**
* 移除数据
* @param key 键
* @return 被移除的值
*/
Object remove(String key);
/**
* 清空所有数据
*/
void clear();
/**
* 获取所有键
* @return 键的集合
*/
Set<String> keySet();
/**
* 获取所有数据的副本
* @return 数据映射的副本
*/
Map<String, Object> getAll();
/**
* 批量设置数据
* @param data 数据映射
*/
void putAll(Map<String, Object> data);
/**
* 获取上下文大小
* @return 数据项数量
*/
int size();
/**
* 检查上下文是否为空
* @return 是否为空
*/
boolean isEmpty();
/**
* 创建子上下文
* @return 新的子上下文
*/
FlowContext createChild();
/**
* 获取父上下文
* @return 父上下文,如果没有返回null
*/
FlowContext getParent();
/**
* 获取上下文ID
* @return 唯一标识符
*/
String getId();
/**
* 获取创建时间
* @return 创建时间戳
*/
long getCreatedTime();
/**
* 获取最后修改时间
* @return 最后修改时间戳
*/
long getLastModifiedTime();
}
🔧 DefaultFlowContext实现
java
/**
* 默认的流程上下文实现
* 提供基础的数据存储和检索功能
*/
public class DefaultFlowContext implements FlowContext {
private static final Logger logger = LoggerFactory.getLogger(DefaultFlowContext.class);
private final String id;
private final long createdTime;
private volatile long lastModifiedTime;
private final FlowContext parent;
private final Map<String, Object> data;
private final ReadWriteLock lock;
/**
* 创建根上下文
*/
public DefaultFlowContext() {
this(null);
}
/**
* 创建子上下文
* @param parent 父上下文
*/
public DefaultFlowContext(FlowContext parent) {
this.id = generateId();
this.createdTime = System.currentTimeMillis();
this.lastModifiedTime = this.createdTime;
this.parent = parent;
this.data = new ConcurrentHashMap<>();
this.lock = new ReentrantReadWriteLock();
logger.debug("创建上下文: {}, 父上下文: {}", id,
parent != null ? parent.getId() : "null");
}
@Override
public Object put(String key, Object value) {
validateKey(key);
lock.writeLock().lock();
try {
Object oldValue = data.put(key, value);
updateLastModifiedTime();
logger.trace("设置数据: {} = {} (旧值: {})", key, value, oldValue);
return oldValue;
} finally {
lock.writeLock().unlock();
}
}
@Override
public Object get(String key) {
validateKey(key);
lock.readLock().lock();
try {
// 先从当前上下文查找
Object value = data.get(key);
if (value != null) {
logger.trace("从当前上下文获取数据: {} = {}", key, value);
return value;
}
// 如果当前上下文没有,从父上下文查找
if (parent != null) {
value = parent.get(key);
if (value != null) {
logger.trace("从父上下文获取数据: {} = {}", key, value);
return value;
}
}
logger.trace("未找到数据: {}", key);
return null;
} finally {
lock.readLock().unlock();
}
}
@Override
public <T> T get(String key, T defaultValue) {
Object value = get(key);
if (value == null) {
return defaultValue;
}
try {
@SuppressWarnings("unchecked")
T result = (T) value;
return result;
} catch (ClassCastException e) {
logger.warn("数据类型转换失败: {} = {}, 期望类型: {}, 实际类型: {}",
key, value, defaultValue.getClass().getSimpleName(),
value.getClass().getSimpleName());
return defaultValue;
}
}
@Override
public <T> T get(String key, Class<T> type) {
Object value = get(key);
if (value == null) {
return null;
}
if (type.isInstance(value)) {
return type.cast(value);
}
// 尝试类型转换
try {
return convertValue(value, type);
} catch (Exception e) {
throw new ClassCastException(
String.format("无法将 %s 转换为 %s: %s",
value.getClass().getSimpleName(),
type.getSimpleName(),
e.getMessage())
);
}
}
@Override
public boolean containsKey(String key) {
validateKey(key);
lock.readLock().lock();
try {
// 检查当前上下文
if (data.containsKey(key)) {
return true;
}
// 检查父上下文
return parent != null && parent.containsKey(key);
} finally {
lock.readLock().unlock();
}
}
@Override
public Object remove(String key) {
validateKey(key);
lock.writeLock().lock();
try {
Object removedValue = data.remove(key);
if (removedValue != null) {
updateLastModifiedTime();
logger.trace("移除数据: {} = {}", key, removedValue);
}
return removedValue;
} finally {
lock.writeLock().unlock();
}
}
@Override
public void clear() {
lock.writeLock().lock();
try {
int size = data.size();
data.clear();
updateLastModifiedTime();
logger.debug("清空上下文数据,移除 {} 项", size);
} finally {
lock.writeLock().unlock();
}
}
@Override
public Set<String> keySet() {
lock.readLock().lock();
try {
Set<String> keys = new HashSet<>(data.keySet());
// 添加父上下文的键
if (parent != null) {
keys.addAll(parent.keySet());
}
return keys;
} finally {
lock.readLock().unlock();
}
}
@Override
public Map<String, Object> getAll() {
lock.readLock().lock();
try {
Map<String, Object> result = new HashMap<>();
// 先添加父上下文的数据
if (parent != null) {
result.putAll(parent.getAll());
}
// 再添加当前上下文的数据(会覆盖父上下文的同名键)
result.putAll(data);
return result;
} finally {
lock.readLock().unlock();
}
}
@Override
public void putAll(Map<String, Object> data) {
if (data == null || data.isEmpty()) {
return;
}
lock.writeLock().lock();
try {
for (Map.Entry<String, Object> entry : data.entrySet()) {
validateKey(entry.getKey());
}
this.data.putAll(data);
updateLastModifiedTime();
logger.debug("批量设置数据,共 {} 项", data.size());
} finally {
lock.writeLock().unlock();
}
}
@Override
public int size() {
lock.readLock().lock();
try {
return data.size();
} finally {
lock.readLock().unlock();
}
}
@Override
public boolean isEmpty() {
lock.readLock().lock();
try {
return data.isEmpty();
} finally {
lock.readLock().unlock();
}
}
@Override
public FlowContext createChild() {
FlowContext child = new DefaultFlowContext(this);
logger.debug("创建子上下文: {} -> {}", this.id, child.getId());
return child;
}
@Override
public FlowContext getParent() {
return parent;
}
@Override
public String getId() {
return id;
}
@Override
public long getCreatedTime() {
return createdTime;
}
@Override
public long getLastModifiedTime() {
return lastModifiedTime;
}
/**
* 生成唯一ID
*/
private String generateId() {
return "ctx-" + System.currentTimeMillis() + "-" +
Integer.toHexString(System.identityHashCode(this));
}
/**
* 验证键名
*/
private void validateKey(String key) {
if (key == null || key.trim().isEmpty()) {
throw new IllegalArgumentException("键名不能为空");
}
if (key.length() > 255) {
throw new IllegalArgumentException("键名长度不能超过255个字符");
}
// 检查特殊字符
if (key.contains(".") && !isValidDottedKey(key)) {
throw new IllegalArgumentException("无效的键名格式: " + key);
}
}
/**
* 检查是否为有效的点分键名
*/
private boolean isValidDottedKey(String key) {
String[] parts = key.split("\.");
for (String part : parts) {
if (part.isEmpty() || !part.matches("[a-zA-Z_][a-zA-Z0-9_]*")) {
return false;
}
}
return true;
}
/**
* 更新最后修改时间
*/
private void updateLastModifiedTime() {
this.lastModifiedTime = System.currentTimeMillis();
}
/**
* 类型转换
*/
@SuppressWarnings("unchecked")
private <T> T convertValue(Object value, Class<T> type) {
if (value == null) {
return null;
}
// 字符串转换
if (type == String.class) {
return (T) value.toString();
}
// 数字转换
if (value instanceof Number) {
Number number = (Number) value;
if (type == Integer.class || type == int.class) {
return (T) Integer.valueOf(number.intValue());
}
if (type == Long.class || type == long.class) {
return (T) Long.valueOf(number.longValue());
}
if (type == Double.class || type == double.class) {
return (T) Double.valueOf(number.doubleValue());
}
if (type == Float.class || type == float.class) {
return (T) Float.valueOf(number.floatValue());
}
if (type == Boolean.class || type == boolean.class) {
return (T) Boolean.valueOf(number.intValue() != 0);
}
}
// 字符串到数字的转换
if (value instanceof String) {
String str = (String) value;
try {
if (type == Integer.class || type == int.class) {
return (T) Integer.valueOf(str);
}
if (type == Long.class || type == long.class) {
return (T) Long.valueOf(str);
}
if (type == Double.class || type == double.class) {
return (T) Double.valueOf(str);
}
if (type == Float.class || type == float.class) {
return (T) Float.valueOf(str);
}
if (type == Boolean.class || type == boolean.class) {
return (T) Boolean.valueOf(str);
}
} catch (NumberFormatException e) {
throw new IllegalArgumentException("无法将字符串 '" + str + "' 转换为 " + type.getSimpleName());
}
}
// 布尔转换
if (value instanceof Boolean && (type == String.class)) {
return (T) value.toString();
}
throw new IllegalArgumentException(
String.format("不支持从 %s 转换到 %s",
value.getClass().getSimpleName(), type.getSimpleName())
);
}
@Override
public String toString() {
return String.format("FlowContext{id='%s', size=%d, parent=%s}",
id, size(), parent != null ? parent.getId() : "null");
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
DefaultFlowContext that = (DefaultFlowContext) obj;
return Objects.equals(id, that.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
🔒 ThreadSafeFlowContext - 线程安全增强
java
/**
* 线程安全的流程上下文装饰器
* 在DefaultFlowContext基础上增强线程安全性
*/
public class ThreadSafeFlowContext implements FlowContext {
private static final Logger logger = LoggerFactory.getLogger(ThreadSafeFlowContext.class);
private final FlowContext delegate;
private final ReadWriteLock globalLock;
private final Map<String, ReadWriteLock> keyLocks;
public ThreadSafeFlowContext(FlowContext delegate) {
this.delegate = delegate;
this.globalLock = new ReentrantReadWriteLock();
this.keyLocks = new ConcurrentHashMap<>();
}
@Override
public Object put(String key, Object value) {
ReadWriteLock keyLock = getKeyLock(key);
keyLock.writeLock().lock();
try {
return delegate.put(key, value);
} finally {
keyLock.writeLock().unlock();
}
}
@Override
public Object get(String key) {
ReadWriteLock keyLock = getKeyLock(key);
keyLock.readLock().lock();
try {
return delegate.get(key);
} finally {
keyLock.readLock().unlock();
}
}
@Override
public <T> T get(String key, T defaultValue) {
ReadWriteLock keyLock = getKeyLock(key);
keyLock.readLock().lock();
try {
return delegate.get(key, defaultValue);
} finally {
keyLock.readLock().unlock();
}
}
@Override
public <T> T get(String key, Class<T> type) {
ReadWriteLock keyLock = getKeyLock(key);
keyLock.readLock().lock();
try {
return delegate.get(key, type);
} finally {
keyLock.readLock().unlock();
}
}
@Override
public boolean containsKey(String key) {
ReadWriteLock keyLock = getKeyLock(key);
keyLock.readLock().lock();
try {
return delegate.containsKey(key);
} finally {
keyLock.readLock().unlock();
}
}
@Override
public Object remove(String key) {
ReadWriteLock keyLock = getKeyLock(key);
keyLock.writeLock().lock();
try {
Object result = delegate.remove(key);
// 清理不再使用的锁
if (!delegate.containsKey(key)) {
keyLocks.remove(key);
}
return result;
} finally {
keyLock.writeLock().unlock();
}
}
@Override
public void clear() {
globalLock.writeLock().lock();
try {
delegate.clear();
keyLocks.clear();
} finally {
globalLock.writeLock().unlock();
}
}
@Override
public Set<String> keySet() {
globalLock.readLock().lock();
try {
return new HashSet<>(delegate.keySet());
} finally {
globalLock.readLock().unlock();
}
}
@Override
public Map<String, Object> getAll() {
globalLock.readLock().lock();
try {
return new HashMap<>(delegate.getAll());
} finally {
globalLock.readLock().unlock();
}
}
@Override
public void putAll(Map<String, Object> data) {
if (data == null || data.isEmpty()) {
return;
}
// 按键名排序,避免死锁
List<String> sortedKeys = new ArrayList<>(data.keySet());
Collections.sort(sortedKeys);
// 获取所有需要的锁
List<ReadWriteLock> locks = new ArrayList<>();
for (String key : sortedKeys) {
locks.add(getKeyLock(key));
}
// 按顺序获取写锁
for (ReadWriteLock lock : locks) {
lock.writeLock().lock();
}
try {
delegate.putAll(data);
} finally {
// 按相反顺序释放锁
for (int i = locks.size() - 1; i >= 0; i--) {
locks.get(i).writeLock().unlock();
}
}
}
@Override
public int size() {
globalLock.readLock().lock();
try {
return delegate.size();
} finally {
globalLock.readLock().unlock();
}
}
@Override
public boolean isEmpty() {
globalLock.readLock().lock();
try {
return delegate.isEmpty();
} finally {
globalLock.readLock().unlock();
}
}
@Override
public FlowContext createChild() {
// 子上下文也应该是线程安全的
FlowContext childDelegate = delegate.createChild();
return new ThreadSafeFlowContext(childDelegate);
}
@Override
public FlowContext getParent() {
return delegate.getParent();
}
@Override
public String getId() {
return delegate.getId();
}
@Override
public long getCreatedTime() {
return delegate.getCreatedTime();
}
@Override
public long getLastModifiedTime() {
return delegate.getLastModifiedTime();
}
/**
* 获取键对应的锁
*/
private ReadWriteLock getKeyLock(String key) {
return keyLocks.computeIfAbsent(key, k -> new ReentrantReadWriteLock());
}
/**
* 执行原子操作
* @param key 键
* @param operation 操作
* @return 操作结果
*/
public <T> T atomicOperation(String key, Function<Object, T> operation) {
ReadWriteLock keyLock = getKeyLock(key);
keyLock.writeLock().lock();
try {
Object currentValue = delegate.get(key);
return operation.apply(currentValue);
} finally {
keyLock.writeLock().unlock();
}
}
/**
* 条件更新
* @param key 键
* @param expectedValue 期望值
* @param newValue 新值
* @return 是否更新成功
*/
public boolean compareAndSet(String key, Object expectedValue, Object newValue) {
ReadWriteLock keyLock = getKeyLock(key);
keyLock.writeLock().lock();
try {
Object currentValue = delegate.get(key);
if (Objects.equals(currentValue, expectedValue)) {
delegate.put(key, newValue);
return true;
}
return false;
} finally {
keyLock.writeLock().unlock();
}
}
@Override
public String toString() {
return "ThreadSafe[" + delegate.toString() + "]";
}
}
💾 SerializableFlowContext - 序列化支持
java
/**
* 可序列化的流程上下文
* 支持上下文的持久化和恢复
*/
public class SerializableFlowContext extends DefaultFlowContext implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(SerializableFlowContext.class);
// 序列化时排除的键(敏感信息)
private final Set<String> excludeKeys = new HashSet<>();
public SerializableFlowContext() {
super();
}
public SerializableFlowContext(FlowContext parent) {
super(parent);
}
/**
* 添加序列化排除的键
* @param key 要排除的键
*/
public void addExcludeKey(String key) {
excludeKeys.add(key);
}
/**
* 移除序列化排除的键
* @param key 要移除的键
*/
public void removeExcludeKey(String key) {
excludeKeys.remove(key);
}
/**
* 序列化到字节数组
* @return 序列化后的字节数组
*/
public byte[] serialize() {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
// 创建序列化数据
SerializationData data = createSerializationData();
oos.writeObject(data);
byte[] result = baos.toByteArray();
logger.debug("上下文序列化完成,大小: {} 字节", result.length);
return result;
} catch (IOException e) {
throw new RuntimeException("上下文序列化失败", e);
}
}
/**
* 从字节数组反序列化
* @param data 序列化的字节数组
* @return 反序列化的上下文
*/
public static SerializableFlowContext deserialize(byte[] data) {
try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
ObjectInputStream ois = new ObjectInputStream(bais)) {
SerializationData serData = (SerializationData) ois.readObject();
SerializableFlowContext context = new SerializableFlowContext();
context.restoreFromSerializationData(serData);
logger.debug("上下文反序列化完成,数据项: {}", context.size());
return context;
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException("上下文反序列化失败", e);
}
}
/**
* 序列化到JSON字符串
* @return JSON字符串
*/
public String toJson() {
try {
ObjectMapper mapper = new ObjectMapper();
SerializationData data = createSerializationData();
return mapper.writeValueAsString(data);
} catch (Exception e) {
throw new RuntimeException("JSON序列化失败", e);
}
}
/**
* 从JSON字符串反序列化
* @param json JSON字符串
* @return 反序列化的上下文
*/
public static SerializableFlowContext fromJson(String json) {
try {
ObjectMapper mapper = new ObjectMapper();
SerializationData data = mapper.readValue(json, SerializationData.class);
SerializableFlowContext context = new SerializableFlowContext();
context.restoreFromSerializationData(data);
return context;
} catch (Exception e) {
throw new RuntimeException("JSON反序列化失败", e);
}
}
/**
* 创建序列化数据
*/
private SerializationData createSerializationData() {
Map<String, Object> serializableData = new HashMap<>();
for (Map.Entry<String, Object> entry : getAll().entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// 跳过排除的键
if (excludeKeys.contains(key)) {
continue;
}
// 只序列化可序列化的值
if (isSerializable(value)) {
serializableData.put(key, value);
} else {
logger.warn("跳过不可序列化的值: {} = {}", key, value.getClass().getSimpleName());
}
}
return new SerializationData(
getId(),
getCreatedTime(),
getLastModifiedTime(),
serializableData
);
}
/**
* 从序列化数据恢复
*/
private void restoreFromSerializationData(SerializationData data) {
clear();
putAll(data.getData());
}
/**
* 检查值是否可序列化
*/
private boolean isSerializable(Object value) {
if (value == null) {
return true;
}
// 基本类型和常用类型
if (value instanceof String ||
value instanceof Number ||
value instanceof Boolean ||
value instanceof Date) {
return true;
}
// 集合类型(递归检查元素)
if (value instanceof Collection) {
Collection<?> collection = (Collection<?>) value;
return collection.stream().allMatch(this::isSerializable);
}
if (value instanceof Map) {
Map<?, ?> map = (Map<?, ?>) value;
return map.entrySet().stream()
.allMatch(entry -> isSerializable(entry.getKey()) && isSerializable(entry.getValue()));
}
// 实现了Serializable接口
return value instanceof Serializable;
}
/**
* 序列化数据结构
*/
private static class SerializationData implements Serializable {
private static final long serialVersionUID = 1L;
private final String id;
private final long createdTime;
private final long lastModifiedTime;
private final Map<String, Object> data;
public SerializationData(String id, long createdTime, long lastModifiedTime, Map<String, Object> data) {
this.id = id;
this.createdTime = createdTime;
this.lastModifiedTime = lastModifiedTime;
this.data = data;
}
public String getId() { return id; }
public long getCreatedTime() { return createdTime; }
public long getLastModifiedTime() { return lastModifiedTime; }
public Map<String, Object> getData() { return data; }
}
}
🔍 MonitoringFlowContext - 监控装饰器
java
/**
* 监控装饰器
* 记录上下文的访问和修改历史
*/
public class MonitoringFlowContext implements FlowContext {
private static final Logger logger = LoggerFactory.getLogger(MonitoringFlowContext.class);
private final FlowContext delegate;
private final List<ContextEvent> events = new CopyOnWriteArrayList<>();
private final AtomicLong eventCounter = new AtomicLong(0);
public MonitoringFlowContext(FlowContext delegate) {
this.delegate = delegate;
recordEvent(ContextEventType.CREATED, null, null, null);
}
@Override
public Object put(String key, Object value) {
Object oldValue = delegate.put(key, value);
recordEvent(ContextEventType.PUT, key, oldValue, value);
return oldValue;
}
@Override
public Object get(String key) {
Object value = delegate.get(key);
recordEvent(ContextEventType.GET, key, null, value);
return value;
}
@Override
public <T> T get(String key, T defaultValue) {
T value = delegate.get(key, defaultValue);
recordEvent(ContextEventType.GET, key, defaultValue, value);
return value;
}
@Override
public <T> T get(String key, Class<T> type) {
T value = delegate.get(key, type);
recordEvent(ContextEventType.GET, key, null, value);
return value;
}
@Override
public boolean containsKey(String key) {
boolean result = delegate.containsKey(key);
recordEvent(ContextEventType.CONTAINS, key, null, result);
return result;
}
@Override
public Object remove(String key) {
Object removedValue = delegate.remove(key);
recordEvent(ContextEventType.REMOVE, key, removedValue, null);
return removedValue;
}
@Override
public void clear() {
int sizeBefore = delegate.size();
delegate.clear();
recordEvent(ContextEventType.CLEAR, null, sizeBefore, 0);
}
@Override
public Set<String> keySet() {
Set<String> keys = delegate.keySet();
recordEvent(ContextEventType.KEY_SET, null, null, keys.size());
return keys;
}
@Override
public Map<String, Object> getAll() {
Map<String, Object> data = delegate.getAll();
recordEvent(ContextEventType.GET_ALL, null, null, data.size());
return data;
}
@Override
public void putAll(Map<String, Object> data) {
delegate.putAll(data);
recordEvent(ContextEventType.PUT_ALL, null, null, data.size());
}
@Override
public int size() {
return delegate.size();
}
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
@Override
public FlowContext createChild() {
FlowContext child = delegate.createChild();
recordEvent(ContextEventType.CREATE_CHILD, null, null, child.getId());
return new MonitoringFlowContext(child);
}
@Override
public FlowContext getParent() {
return delegate.getParent();
}
@Override
public String getId() {
return delegate.getId();
}
@Override
public long getCreatedTime() {
return delegate.getCreatedTime();
}
@Override
public long getLastModifiedTime() {
return delegate.getLastModifiedTime();
}
/**
* 记录事件
*/
private void recordEvent(ContextEventType type, String key, Object oldValue, Object newValue) {
ContextEvent event = new ContextEvent(
eventCounter.incrementAndGet(),
System.currentTimeMillis(),
Thread.currentThread().getName(),
type,
key,
oldValue,
newValue
);
events.add(event);
// 限制事件数量,避免内存泄漏
if (events.size() > 1000) {
events.remove(0);
}
logger.trace("上下文事件: {}", event);
}
/**
* 获取事件历史
* @return 事件列表的副本
*/
public List<ContextEvent> getEventHistory() {
return new ArrayList<>(events);
}
/**
* 获取指定类型的事件
* @param type 事件类型
* @return 匹配的事件列表
*/
public List<ContextEvent> getEventsByType(ContextEventType type) {
return events.stream()
.filter(event -> event.getType() == type)
.collect(Collectors.toList());
}
/**
* 获取指定键的事件
* @param key 键名
* @return 匹配的事件列表
*/
public List<ContextEvent> getEventsByKey(String key) {
return events.stream()
.filter(event -> Objects.equals(event.getKey(), key))
.collect(Collectors.toList());
}
/**
* 获取统计信息
* @return 统计信息
*/
public ContextStatistics getStatistics() {
Map<ContextEventType, Long> eventCounts = events.stream()
.collect(Collectors.groupingBy(
ContextEvent::getType,
Collectors.counting()
));
Set<String> accessedKeys = events.stream()
.map(ContextEvent::getKey)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
return new ContextStatistics(
events.size(),
eventCounts,
accessedKeys.size(),
accessedKeys
);
}
/**
* 上下文事件类型
*/
public enum ContextEventType {
CREATED, PUT, GET, CONTAINS, REMOVE, CLEAR,
KEY_SET, GET_ALL, PUT_ALL, CREATE_CHILD
}
/**
* 上下文事件
*/
public static class ContextEvent {
private final long sequence;
private final long timestamp;
private final String threadName;
private final ContextEventType type;
private final String key;
private final Object oldValue;
private final Object newValue;
public ContextEvent(long sequence, long timestamp, String threadName,
ContextEventType type, String key, Object oldValue, Object newValue) {
this.sequence = sequence;
this.timestamp = timestamp;
this.threadName = threadName;
this.type = type;
this.key = key;
this.oldValue = oldValue;
this.newValue = newValue;
}
// getter方法...
public long getSequence() { return sequence; }
public long getTimestamp() { return timestamp; }
public String getThreadName() { return threadName; }
public ContextEventType getType() { return type; }
public String getKey() { return key; }
public Object getOldValue() { return oldValue; }
public Object getNewValue() { return newValue; }
@Override
public String toString() {
return String.format("ContextEvent{seq=%d, time=%d, thread='%s', type=%s, key='%s', old=%s, new=%s}",
sequence, timestamp, threadName, type, key, oldValue, newValue);
}
}
/**
* 上下文统计信息
*/
public static class ContextStatistics {
private final int totalEvents;
private final Map<ContextEventType, Long> eventCounts;
private final int uniqueKeysAccessed;
private final Set<String> accessedKeys;
public ContextStatistics(int totalEvents, Map<ContextEventType, Long> eventCounts,
int uniqueKeysAccessed, Set<String> accessedKeys) {
this.totalEvents = totalEvents;
this.eventCounts = eventCounts;
this.uniqueKeysAccessed = uniqueKeysAccessed;
this.accessedKeys = accessedKeys;
}
// getter方法...
public int getTotalEvents() { return totalEvents; }
public Map<ContextEventType, Long> getEventCounts() { return eventCounts; }
public int getUniqueKeysAccessed() { return uniqueKeysAccessed; }
public Set<String> getAccessedKeys() { return accessedKeys; }
@Override
public String toString() {
return String.format("ContextStatistics{totalEvents=%d, uniqueKeys=%d, eventCounts=%s}",
totalEvents, uniqueKeysAccessed, eventCounts);
}
}
}
🧪 上下文测试示例
java
public class FlowContextTest {
@Test
public void testBasicOperations() {
FlowContext context = new DefaultFlowContext();
// 基本操作测试
assertNull(context.put("key1", "value1"));
assertEquals("value1", context.get("key1"));
assertTrue(context.containsKey("key1"));
assertEquals(1, context.size());
assertFalse(context.isEmpty());
// 类型转换测试
context.put("number", 42);
assertEquals(Integer.valueOf(42), context.get("number", Integer.class));
assertEquals("42", context.get("number", String.class));
// 默认值测试
assertEquals("default", context.get("nonexistent", "default"));
// 移除测试
assertEquals("value1", context.remove("key1"));
assertFalse(context.containsKey("key1"));
// 清空测试
context.clear();
assertTrue(context.isEmpty());
}
@Test
public void testHierarchicalContext() {
FlowContext parent = new DefaultFlowContext();
parent.put("parentKey", "parentValue");
parent.put("sharedKey", "parentSharedValue");
FlowContext child = parent.createChild();
child.put("childKey", "childValue");
child.put("sharedKey", "childSharedValue");
// 子上下文可以访问父上下文的数据
assertEquals("parentValue", child.get("parentKey"));
assertEquals("childValue", child.get("childKey"));
// 子上下文的数据会覆盖父上下文的同名数据
assertEquals("childSharedValue", child.get("sharedKey"));
// 父上下文不能访问子上下文的数据
assertNull(parent.get("childKey"));
assertEquals("parentSharedValue", parent.get("sharedKey"));
// 验证层次关系
assertEquals(parent, child.getParent());
assertNull(parent.getParent());
}
@Test
public void testThreadSafety() throws InterruptedException {
FlowContext context = new ThreadSafeFlowContext(new DefaultFlowContext());
int threadCount = 10;
int operationsPerThread = 1000;
CountDownLatch latch = new CountDownLatch(threadCount);
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < threadCount; i++) {
final int threadId = i;
Thread thread = new Thread(() -> {
try {
for (int j = 0; j < operationsPerThread; j++) {
String key = "key-" + threadId + "-" + j;
String value = "value-" + threadId + "-" + j;
context.put(key, value);
assertEquals(value, context.get(key));
if (j % 2 == 0) {
context.remove(key);
}
}
} finally {
latch.countDown();
}
});
threads.add(thread);
thread.start();
}
assertTrue("线程安全测试超时", latch.await(30, TimeUnit.SECONDS));
// 验证最终状态
int expectedSize = threadCount * operationsPerThread / 2;
assertEquals(expectedSize, context.size());
}
@Test
public void testSerialization() {
SerializableFlowContext context = new SerializableFlowContext();
context.put("string", "test");
context.put("number", 42);
context.put("boolean", true);
context.put("list", Arrays.asList(1, 2, 3));
Map<String, Object> map = new HashMap<>();
map.put("nested", "value");
context.put("map", map);
// 序列化和反序列化
byte[] serialized = context.serialize();
SerializableFlowContext restored = SerializableFlowContext.deserialize(serialized);
// 验证数据完整性
assertEquals("test", restored.get("string"));
assertEquals(42, (int) restored.get("number"));
assertEquals(true, restored.get("boolean"));
assertEquals(Arrays.asList(1, 2, 3), restored.get("list"));
@SuppressWarnings("unchecked")
Map<String, Object> restoredMap = (Map<String, Object>) restored.get("map");
assertEquals("value", restoredMap.get("nested"));
}
@Test
public void testMonitoring() {
FlowContext baseContext = new DefaultFlowContext();
MonitoringFlowContext context = new MonitoringFlowContext(baseContext);
// 执行一些操作
context.put("key1", "value1");
context.get("key1");
context.put("key2", "value2");
context.remove("key1");
context.createChild();
// 检查事件历史
List<MonitoringFlowContext.ContextEvent> events = context.getEventHistory();
assertTrue("应该记录了多个事件", events.size() >= 5);
// 检查特定类型的事件
List<MonitoringFlowContext.ContextEvent> putEvents =
context.getEventsByType(MonitoringFlowContext.ContextEventType.PUT);
assertEquals(2, putEvents.size());
// 检查统计信息
MonitoringFlowContext.ContextStatistics stats = context.getStatistics();
assertTrue("总事件数应该大于0", stats.getTotalEvents() > 0);
assertTrue("访问的键数应该大于0", stats.getUniqueKeysAccessed() > 0);
}
@Test
public void testComplexScenario() {
// 创建复杂的上下文层次结构
FlowContext root = new ThreadSafeFlowContext(
new MonitoringFlowContext(
new SerializableFlowContext()
)
);
// 设置根数据
root.put("config.timeout", 30000);
root.put("config.retries", 3);
// 创建子上下文
FlowContext child1 = root.createChild();
child1.put("task.id", "task-001");
child1.put("task.status", "running");
FlowContext child2 = root.createChild();
child2.put("task.id", "task-002");
child2.put("task.status", "pending");
// 验证数据访问
assertEquals(30000, (int) child1.get("config.timeout"));
assertEquals("task-001", child1.get("task.id"));
assertEquals("task-002", child2.get("task.id"));
// 验证数据隔离
assertNull(child1.get("task.id", String.class).equals(child2.get("task.id", String.class)));
// 验证层次结构
assertEquals(root, child1.getParent());
assertEquals(root, child2.getParent());
}
}
🎯 设计亮点
✨ 1. 装饰器模式
- 🎨 功能增强: 通过装饰器添加线程安全、监控、序列化等功能
- 🔧 灵活组合: 可以任意组合不同的装饰器
- 🚀 易于扩展: 添加新功能只需实现新的装饰器
✨ 2. 层次化设计
- 🌳 继承关系: 子上下文可以访问父上下文的数据
- 🔒 数据隔离: 不同分支的数据相互隔离
- 📊 作用域管理: 支持局部变量和全局变量的概念
✨ 3. 类型安全
- 🛡️ 强类型转换: 提供类型安全的数据访问方法
- 🔄 自动转换: 支持常见类型之间的自动转换
- ⚠️ 异常处理: 类型不匹配时提供清晰的错误信息
✨ 4. 并发安全
- 🧵 细粒度锁: 使用键级别的读写锁提高并发性能
- 🔒 死锁避免: 通过锁排序避免死锁
- ⚡ 原子操作: 提供原子性的复合操作
🎉 小结
在这一章中,我们完成了:
- 🏗️ 设计了上下文接口: 定义了完整的上下文操作API
- 🔧 实现了基础上下文: DefaultFlowContext提供核心功能
- 🔒 增强了线程安全: ThreadSafeFlowContext确保并发安全
- 💾 支持了序列化: SerializableFlowContext实现持久化
- 🔍 添加了监控功能: MonitoringFlowContext记录访问历史
- 🧪 提供了完整测试: 验证各种场景和功能
🚀 下一步
在下一章《表达式引擎实现》中,我们将:
- 🔍 设计表达式解析和评估引擎
- 📝 实现多种表达式语法支持
- 🔧 集成脚本引擎和自定义函数
- 🛡️ 实现表达式安全性和沙箱机制
- 🧪 编写表达式引擎的完整测试
💡 思考题:
- 如何设计上下文的版本控制和回滚机制?
- 如何实现上下文数据的懒加载和缓存策略?
- 如何设计分布式环境下的上下文同步机制?