命令框架开发:如何复用已有类实例,无则创建新实例?
解决方法
核心思路是通过实例缓存复用已创建的对象,同时提供开发者手动注册实例的入口,再优化实例创建逻辑来适配无默认构造的类。
1. 维护实例缓存
在框架内部用一个线程安全的映射表存储类与对应实例的关系,确保同一个类只会创建一次实例(除非开发者手动覆盖):
// 框架内部缓存,用ConcurrentHashMap保证多线程安全 private final Map<Class<?>, Object> commandInstanceCache = new ConcurrentHashMap<>();
2. 开放手动注册实例的API
给开发者提供主动注册实例的方法,让他们可以自行控制实例的创建(比如用依赖注入、单例模式生成的实例):
// 开发者调用此方法,注册自己创建的命令类实例 public void registerCommandInstance(Object instance) { if (instance == null) { throw new IllegalArgumentException("命令实例不能为null"); } commandInstanceCache.put(instance.getClass(), instance); }
3. 修改命令调用逻辑
每次执行命令时,先从缓存取实例,取不到再尝试创建,创建后存入缓存复用:
// 获取方法所属的类 Class<?> commandClass = mapping.getMethod().getDeclaringClass(); // 优先从缓存获取实例 Object commandInstance = commandInstanceCache.get(commandClass); if (commandInstance == null) { // 缓存无实例,尝试创建 commandInstance = createCommandInstance(commandClass); // 存入缓存,后续调用复用 commandInstanceCache.put(commandClass, commandInstance); } // 执行命令方法 mapping.getMethod().invoke(commandInstance, paramValues);
4. 优化实例创建逻辑(适配无空构造的类)
针对没有默认空构造的类,要么抛出明确提示让开发者手动注册实例,要么扩展支持自定义构造参数。下面是基础实现:
private Object createCommandInstance(Class<?> clazz) throws ReflectiveOperationException { // 先尝试无参构造 try { Constructor<?> noArgConstructor = clazz.getDeclaredConstructor(); noArgConstructor.setAccessible(true); // 允许访问私有构造 return noArgConstructor.newInstance(); } catch (NoSuchMethodException e) { // 无参构造不存在,抛出异常提示开发者手动注册 throw new IllegalStateException(String.format( "类[%s]没有无参构造函数,请调用registerCommandInstance方法手动注册实例,或配置构造参数", clazz.getName() )); } }
扩展优化(可选)
如果想支持带参数的构造,可以添加注解让开发者标记构造参数:
- 定义
@CommandConstructorParam注解,标记构造参数的默认值 - 在
createCommandInstance中扫描带注解的构造函数,解析参数并创建实例
这样既保留了框架的自动创建能力,又给了开发者足够的控制权。
内容的提问来源于stack exchange,提问作者Stephen
相关产品推荐
相关产品推荐

