Java可通过反射获取方法参数的@Inject注解,结合ConcurrentHashMap容器实现轻量级依赖注入:遍历方法参数→检查@Inject→按value值查bean→构建参数数组→invoke调用。
在 java 中,可以通过反射获取方法参数上的自定义注解,并结合容器(如简单 map 或 concurrenthashmap)实现轻量级依赖注入逻辑。核心在于:遍历目标类的所有声明方法 → 检查方法参数是否标注了特定注解(如 @inject)→ 根据注解元数据从容器中查找并注入对应实例。
定义用于标记依赖的自定义注解
先创建一个运行时保留的注解,用于标注需要自动注入的参数:
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
String value() default "";
}
注意:@Target(ElementType.PARAMETER) 表示该注解只能用在方法参数上;@Retention(RetentionPolicy.RUNTIME) 是反射可用的前提。
扫描并调用带 @Inject 参数的方法
假设有一个服务类,其某个方法希望由框架自动注入依赖:
public class UserService {
public void process(@Inject("emailService") NotificationService service) {
service.send("Hello");
}
}
在注入执行器中,需完成以下步骤:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
立即学习“Java免费学习笔记(深入)”;
- 获取目标对象的 Class 和所有 declaredMethods
- 对每个方法,调用
method.getParameterAnnotations()获取各参数的注解数组 - 遍历每个参数的注解,检查是否存在
@Inject,并提取其value() - 根据 name(如 "emailService")从 bean 容器中查找对应实例
- 构造参数数组,将查到的实例填入对应位置,再用
method.invoke(target, args)调用
手动构建简易 Bean 容器与注入执行器
无需 Spring,几行代码即可模拟基础能力:
Map<String, Object> beans = new ConcurrentHashMap<>();
beans.put("emailService", new EmailServiceImpl());
public void invokeWithInjection(Object target, String methodName) throws Exception {
Method method = target.getClass().getDeclaredMethod(methodName);
Parameter[] params = method.getParameters();
Object[] args = new Object[params.length];
for (int i = 0; i < params.length; i++) {
Inject inject = params[i].getAnnotation(Inject.class);
if (inject != null) {
String key = inject.value().isEmpty()
? params[i].getType().getSimpleName().toLowerCase()
: inject.value();
args[i] = beans.get(key);
}
}
method.setAccessible(true); // 处理 private 方法
method.invoke(target, args);
}
这样调用 invokeWithInjection(new UserService(), "process") 就会自动注入 EmailServiceImpl 实例。
注意事项与常见坑点
- 确保目标方法不是
private或未开启setAccessible(true),否则反射调用会抛出 IllegalAccessException - 参数类型匹配建议增强:可优先按
@Inject("xxx")查找,未指定时尝试按类型名(如EmailService.class→ "emailservice")模糊匹配 - 循环依赖无法自动解决,需提前校验或引入代理机制
- 生产环境不建议直接手写 DI 框架,但理解该过程对调试 Spring、排查
@Autowired失效问题很有帮助

















