ClassGraph不是IOC容器,而是用于高效扫描带注解类的轻量级引擎;它通过构建期或启动初期扫描@Service等注解类,结合反射实现无Spring依赖的自动装配,支持运行时零开销与编译期预扫描。

ClassGraph 本身不是 IOC 容器,但它能高效、安全、零运行时开销地发现带注解的类,是构建轻量级 IOC 自动装配器的理想“扫描引擎”。核心思路是:用 ClassGraph 在构建时或启动初期扫描出所有被业务注解(如 @Service、@Controller、@Component)标记的类,再结合 Java 反射完成实例化与依赖注入——整个过程不依赖 Spring,也无需字节码增强。
明确扫描目标与注解策略
先定义你的业务注解体系,例如:
- 统一基注解
@Bean(或复用 Spring 的@Component,但需注意避免引入 Spring 依赖) - 分层语义注解:
@Service、@Repository、@Controller(可全部用@Retention(RUNTIME)+@Target(TYPE)定义) - 支持元注解:让
@Service自身标注@Bean,这样 ClassGraph 扫描@Bean就自动覆盖所有子类型
关键点:ClassGraph 不关心注解语义,只负责“找到谁用了谁”。你只需确保扫描逻辑按注解类型分类提取即可。
用 ClassGraph 高效获取候选类列表
必须启用注解扫描,并限定包范围,避免全路径扫描带来的性能和内存问题:
- 调用
.enableAnnotationInfo()和.enableClassInfo() - 用
.acceptPackages("com.yourcompany.app")精确指定扫描根包 - 使用
try-with-resources确保ScanResult正确释放资源
示例代码片段:
try (ScanResult scanResult = new ClassGraph().enableClassInfo()
.enableAnnotationInfo()
.acceptPackages("com.example")
.scan()) {
List
List
}
基于扫描结果实现简易 IOC 容器逻辑
扫描得到的是 ClassInfo 列表,接下来要完成三件事:实例化、依赖解析、注册到容器中。
-
实例化:调用
classInfo.loadClass()获取Class>,再用clazz.getDeclaredConstructor().newInstance()创建实例(注意处理无参构造要求) -
依赖注入:遍历类中所有
@Autowired(或自定义@Inject)字段,从已注册的 Bean 中查找匹配类型并设值(可用field.setAccessible(true)+field.set(instance, bean)) -
注册管理:用
ConcurrentHashMap存储单例 Bean,键可为类名、简单名或自定义@Bean(name="xxx")值
注意:ClassGraph 不加载也不初始化类,所有反射操作由你控制,完全规避了 Class.forName() 的副作用风险。
构建时扫描 + 运行时零开销(进阶可选)
若追求极致性能,可将 ClassGraph 扫描移至构建阶段(如 Gradle 注解处理器):
- 在
annotationProcessor中执行扫描,生成 JSON 或 Java 类描述文件(如BeanDefinitions.java) - 运行时直接读取预生成的元数据,跳过任何类路径扫描
- 优势:Android 兼容、冷启动更快、100% 确定性、便于 AOT 编译
这种模式下,ClassGraph 只在编译期工作,运行时容器纯靠反射+预置清单,真正轻量且可控。










