核心思路是通过反射识别并安全实例化实现统一接口的产品类,再利用多态调用具体行为。一、定义Product接口作为契约;二、用注解或包路径标识可加载类;三、扫描、校验(实现接口、有无参构造)、实例化;四、存入List,遍历调用execute()实现自动派发。

核心思路是:用反射获取类信息,靠接口或抽象类统一类型,再通过多态调用具体产品行为。关键不在“扫描”,而在“识别可加载类”和“安全实例化”。
一、定义统一的产品契约(接口或抽象类)
所有可被动态加载的产品类必须实现同一个接口,比如:
Product 接口声明通用方法(如 init()、execute()),不关心具体实现。这是多态的基石——运行时能用 Product 引用指向任意子类实例。
二、约定可扫描的类特征(便于反射识别)
不能盲目扫描所有类,需有明确标识。常用方式有:
- 放在指定包路径下(如 com.example.products.*),扫描该包下所有类
- 添加自定义注解(如 @ProductComponent),反射时只筛选带此注解的类
- 类名符合命名规范(如以 Product 结尾),配合简单字符串匹配
推荐注解方式,语义清晰且可控性强;包扫描适合模块边界明确的场景。
三、用反射完成“发现→校验→实例化”闭环
步骤要严谨,避免运行时异常:
- 用 ClassPathScanningCandidateComponentProvider(Spring)或自研 ClassLoader + URL 扫描,获取候选 Class 对象
- 对每个类,检查是否为接口/抽象类(跳过)、是否实现了 Product 接口(isAssignableFrom)、是否有无参构造(或按需处理带参构造)
- 通过 clazz.getDeclaredConstructor().newInstance() 创建实例,并向上转型为 Product
注意:实例化前务必捕获 InstantiationException、IllegalAccessException 等异常,失败类应记录日志而非中断整个流程。
四、利用多态统一调度,隐藏具体类型
把加载好的实例存入 List
只需遍历列表,调用 product.execute() —— JVM 自动派发到对应子类的具体实现,无需 if-else 判断类型。新增产品类?只要实现接口、加注解、放对位置,重启或热加载后自动生效。

















