package com.imyeyu.inject; import com.imyeyu.inject.annotation.Import; import com.imyeyu.inject.annotation.TimiInjectApplication; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; /** * Timi 控制反转框架 * * @author 夜雨 */ public class TimiInject { private static final Logger log = LoggerFactory.getLogger(TimiInject.class); private final BeanContext context; private final BeanFactory factory; private TimiInject(BeanContext context, BeanFactory factory) { this.context = context; this.factory = factory; } /** * 启动应用并初始化容器 */ public static TimiInject run(Class applicationClass, String... args) { long startTime = System.currentTimeMillis(); log.info("Starting {} ...", applicationClass.getSimpleName()); TimiInjectApplication annotation = applicationClass.getAnnotation(TimiInjectApplication.class); if (annotation == null) { throw new InjectException("Application class must be annotated with @TimiInjectApplication"); } BeanContext context = new BeanContext(); BeanFactory factory = new BeanFactory(context); BeanScanner scanner = new BeanScanner(context); String[] basePackages = annotation.value(); if (basePackages.length == 0) { basePackages = new String[]{applicationClass.getPackage().getName()}; } scanner.scan(basePackages); processImports(applicationClass, scanner, context); factory.initializeSingletons(); long elapsed = System.currentTimeMillis() - startTime; log.info("Started {} in {} ms ({} beans)", applicationClass.getSimpleName(), elapsed, context.getAllDefinitions().size()); return new TimiInject(context, factory); } /** * 依赖注入 - 获取 Bean 实例(按类型) */ public T di(Class type) { return factory.getBean(type); } /** * 依赖注入 - 获取 Bean 实例(按名称和类型) */ public T di(String name, Class type) { return factory.getBean(name, type); } /** * 控制反转 - 手动注册 Bean 实例 */ public void ioc(String name, Object bean) { context.registerSingleton(name, bean); log.debug("Registered singleton bean: {} ({})", name, bean.getClass().getName()); } /** * 导出依赖图 */ public String exportDependencyGraph() { StringBuilder graph = new StringBuilder(); graph.append("=== Dependency Graph ===\n\n"); for (BeanDefinition definition : context.getAllDefinitions()) { graph.append(formatBeanInfo(definition)); graph.append("\n"); } return graph.toString(); } private String formatBeanInfo(BeanDefinition definition) { StringBuilder info = new StringBuilder(); info.append("Bean: ").append(definition.getName()).append("\n"); info.append(" Type: ").append(definition.getType().getName()).append("\n"); info.append(" Scope: ").append(definition.getScope()).append("\n"); info.append(" Primary: ").append(definition.isPrimary()).append("\n"); if (definition.isFactoryBean()) { info.append(" Factory: @Bean ").append(definition.getFactoryMethod().getName()).append("()\n"); } else if (definition.getConstructor() != null) { info.append(" Constructor: ").append(definition.getConstructor().getParameterCount()) .append(" parameters\n"); } if (definition.getPostConstruct() != null) { info.append(" PostConstruct: ").append(definition.getPostConstruct().getName()).append("()\n"); } return info.toString(); } private static void processImports(Class applicationClass, BeanScanner scanner, BeanContext context) { if (!applicationClass.isAnnotationPresent(Import.class)) { return; } Import importAnnotation = applicationClass.getAnnotation(Import.class); Class[] importClasses = importAnnotation.value(); for (Class importClass : importClasses) { if (Module.class.isAssignableFrom(importClass)) { try { Module module = (Module) importClass.getDeclaredConstructor().newInstance(); module.configure(context); log.debug("Loaded module: {}", importClass.getName()); } catch (Exception e) { throw new InjectException("Failed to instantiate module: " + importClass.getName(), e); } } else { scanner.processClass(importClass); log.debug("Imported configuration: {}", importClass.getName()); } } } }