You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为自研分析库构建原生依赖注入框架?

自研轻量依赖注入框架(按需实例化版)

核心思路

解决你之前一次性初始化所有类的问题,核心是懒加载+按需创建:不提前实例化所有类,而是在首次请求实例时才完成初始化,并缓存已创建的单例实例。通过反射解析依赖关系,递归创建所需的依赖对象。

关键组件实现

1. 定义核心注解

用自定义注解标记可被DI管理的类,以及需要注入的构造方法:

// 标记类可被DI容器管理,默认单例
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Injectable {
    boolean singleton() default true;
}

// 标记构造方法(用于构造注入)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CONSTRUCTOR)
public @interface Inject {
}

2. 实现DI容器核心类

容器负责注册表管理、实例懒加载、依赖解析:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

public class Injector {
    // 单例实例缓存:存储已创建的单例对象
    private final Map<Class<?>, Object> singletonCache = new ConcurrentHashMap<>();
    // 构造方法缓存:避免重复反射解析构造方法
    private final Map<Class<?>, Constructor<?>> constructorCache = new ConcurrentHashMap<>();

    // 获取实例的入口方法
    @SuppressWarnings("unchecked")
    public <T> T getInstance(Class<T> clazz) {
        // 单例类先检查缓存
        if (clazz.isAnnotationPresent(Injectable.class)) {
            Injectable injectable = clazz.getAnnotation(Injectable.class);
            if (injectable.singleton()) {
                Object instance = singletonCache.get(clazz);
                if (instance != null) {
                    return (T) instance;
                }
            }
        }

        // 解析构造方法并创建实例
        Constructor<?> constructor = getInjectConstructor(clazz);
        if (constructor == null) {
            throw new IllegalArgumentException("No valid constructor found for " + clazz.getName());
        }

        // 递归创建构造方法的依赖参数
        Object[] params = new Object[constructor.getParameterCount()];
        for (int i = 0; i < params.length; i++) {
            Class<?> paramType = constructor.getParameterTypes()[i];
            params[i] = getInstance(paramType);
        }

        // 实例化对象
        try {
            T instance = (T) constructor.newInstance(params);
            // 单例类存入缓存
            if (clazz.isAnnotationPresent(Injectable.class) && clazz.getAnnotation(Injectable.class).singleton()) {
                singletonCache.put(clazz, instance);
            }
            return instance;
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException("Failed to create instance for " + clazz.getName(), e);
        }
    }

    // 获取带@Inject注解的构造方法,无则尝试无参构造
    private Constructor<?> getInjectConstructor(Class<?> clazz) {
        Constructor<?> cached = constructorCache.get(clazz);
        if (cached != null) {
            return cached;
        }

        // 优先找带@Inject的构造方法
        for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
            if (constructor.isAnnotationPresent(Inject.class)) {
                constructor.setAccessible(true);
                constructorCache.put(clazz, constructor);
                return constructor;
            }
        }

        //  fallback到无参构造
        try {
            Constructor<?> noArgConstructor = clazz.getDeclaredConstructor();
            noArgConstructor.setAccessible(true);
            constructorCache.put(clazz, noArgConstructor);
            return noArgConstructor;
        } catch (NoSuchMethodException e) {
            return null;
        }
    }
}

3. 框架使用示例

标记你的业务类:

// 单例分析追踪器
@Injectable
public class AnalyticsTracker {
    private final EventLogger logger;

    // 构造注入依赖
    @Inject
    public AnalyticsTracker(EventLogger logger) {
        this.logger = logger;
    }

    public void trackEvent(String event) {
        logger.log("Tracked event: " + event);
    }
}

// 单例事件日志器
@Injectable
public class EventLogger {
    @Inject
    public EventLogger() {
        // 无参构造
    }

    public void log(String message) {
        System.out.println(message);
    }
}

// 多实例会话类
@Injectable(singleton = false)
public class UserSession {
    @Inject
    public UserSession() {}
}

获取实例:

public class Main {
    public static void main(String[] args) {
        Injector injector = new Injector();
        // 首次调用才初始化AnalyticsTracker和依赖的EventLogger
        AnalyticsTracker tracker = injector.getInstance(AnalyticsTracker.class);
        tracker.trackEvent("app_start");

        // 单例验证:两次获取是同一个实例
        AnalyticsTracker tracker2 = injector.getInstance(AnalyticsTracker.class);
        System.out.println(tracker == tracker2); // 输出true

        // 多实例验证:每次获取都是新对象
        UserSession session1 = injector.getInstance(UserSession.class);
        UserSession session2 = injector.getInstance(UserSession.class);
        System.out.println(session1 == session2); // 输出false
    }
}

可选优化点

  • 循环依赖处理:添加Set<Class<?>> creatingClasses记录正在创建的类,检测到循环依赖时抛出异常。
  • 字段注入支持:实例创建后,遍历类的字段,注入带@Inject标记的私有字段。
  • 预扫描优化:容器初始化时扫描指定包下的@Injectable类,提前解析构造方法元数据,减少运行时反射开销。
  • 自定义作用域:扩展支持会话级、请求级等自定义作用域,不局限于单例/多实例。

内容的提问来源于stack exchange,提问作者SdkDroider177

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 10:57:13