05 - 上下文管理机制 📦

🎯 目标: 设计线程安全、层次化的上下文管理系统,支持数据共享和隔离

🤔 为什么需要上下文管理?

在流程编排中,上下文是数据流转的核心:

  • 📊 数据共享: 步骤之间需要传递和共享数据
  • 🔒 数据隔离: 并行执行时需要隔离不同分支的数据
  • 🌳 层次结构: 支持父子上下文的继承关系
  • 💾 持久化: 支持上下文的序列化和恢复
  • 🔍 监控追踪: 记录数据变更历史和访问轨迹

🏗️ 上下文架构设计

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记录访问历史
  • 🧪 提供了完整测试: 验证各种场景和功能

🚀 下一步

在下一章《表达式引擎实现》中,我们将:

  • 🔍 设计表达式解析和评估引擎
  • 📝 实现多种表达式语法支持
  • 🔧 集成脚本引擎和自定义函数
  • 🛡️ 实现表达式安全性和沙箱机制
  • 🧪 编写表达式引擎的完整测试

💡 思考题:

  1. 如何设计上下文的版本控制和回滚机制?
  2. 如何实现上下文数据的懒加载和缓存策略?
  3. 如何设计分布式环境下的上下文同步机制?
相关推荐
石小石Orz13 分钟前
效率提升一倍!谈谈我的高效开发工具链
前端·后端·trae
孟永峰_Java1 小时前
凌晨线上崩盘:NoClassDefFoundError血案纪实!日志里这行「小字」才是救世主
后端·代码规范
whitepure1 小时前
万字详解Java中的IO及序列化
java·后端
大得3692 小时前
django生成迁移文件,执行生成到数据库
后端·python·django
寻月隐君2 小时前
Rust Web 开发实战:使用 SQLx 连接 PostgreSQL 数据库
后端·rust·github
RainbowSea2 小时前
伙伴匹配系统(移动端 H5 网站(APP 风格)基于Spring Boot 后端 + Vue3 - 06
java·spring boot·后端
Keya2 小时前
MacOS端口被占用的解决方法
前端·后端·设计模式
用户9096783069432 小时前
Python 判断一个字符串中是否含有数字
后端
jakeswang2 小时前
应用缓存不止是Redis!——亿级流量系统架构设计系列
redis·分布式·后端·缓存
RainbowSea2 小时前
伙伴匹配系统(移动端 H5 网站(APP 风格)基于Spring Boot 后端 + Vue3 - 05
vue.js·spring boot·后端