implement lightweight IOC/DI framework

- Add annotation system (@Component, @Service, @Configuration, @Bean, @Inject, @Qualifier, @Primary, @Scope, @PostConstruct, @Import, @TimiInjectApplication)
- Implement BeanContext for managing bean instances and definitions
- Implement BeanScanner for component scanning (file system and jar)
- Implement BeanFactory with constructor injection and lifecycle support
- Support @Configuration and @Bean factory methods
- Support @Qualifier and @Primary for multi-implementation
- Support @Scope (singleton/prototype)
- Support @PostConstruct lifecycle callback
- Support @Import and Module extension
- Add circular dependency detection
- Add dependency graph export
- Add demo and test cases

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Timi
2026-01-11 12:26:14 +08:00
parent 05606eda74
commit 71be7c07c0
43 changed files with 1429 additions and 1129 deletions

View File

@@ -1,26 +1,21 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 控制反转(通用对象),注解在类上后该类将被 TimiInject 实例化并控制反转,后续执行注入
* Bean 工厂方法注解,用于 @Configuration 类中
*
* @author 夜雨
* @since 2024-07-19 15:48
*/
@Target({ElementType.TYPE})
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
/**
* 对象名称,非空时注入需要明确执行
*
* @return 对象名称
*/
String value() default "";
/**
* Bean 名称,默认为方法名
*/
String value() default "";
}

View File

@@ -1,26 +1,21 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 控制反转(组件),注解在类上后该类将被 TimiInject 实例化并控制反转,后续执行注入
* 通用组件注解
*
* @author 夜雨
* @version 2022-03-04 23:16
*/
@Target({ElementType.TYPE})
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
/**
* 组件名称,非空时注入需要明确执行
*
* @return 组件名称
*/
String value() default "";
/**
* Bean 名称,默认为类名首字母小写
*/
String value() default "";
}

View File

@@ -1,19 +1,22 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 父级控制反转通常用于父级存在控制反转子类时使用父级可以继续使用此注解
* 配置类注解
*
* @author 夜雨
* @version 2023-02-28 11:42
*/
@Target({ElementType.TYPE})
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SuperIOC {
@Component
public @interface Configuration {
/**
* Bean 名称默认为类名首字母小写
*/
String value() default "";
}

View File

@@ -1,26 +1,22 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 控制反转(控制器),注解在类上后该类将被 TimiInject 实例化并控制反转,后续执行注入
* 控制器组件注解
*
* @author 夜雨
* @version 2022-03-04 23:16
*/
@Target({ElementType.TYPE})
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
/**
* 控制器名称,非空时注入需要明确执行
*
* @return 控制器名称
*/
String value() default "";
/**
* Bean 名称,默认为类名首字母小写
*/
String value() default "";
}

View File

@@ -1,22 +0,0 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <p>异步控制反转,控制反转的类或 {@link IOCReturn} 方法使用此注解将会在异步线程中实例化或调用。
* 此注解不影响注入流程。
* <p>此注解对实例化比较耗时的动作有明显的速度提升,有 {@link IOCPriority} 的效果,对实例化耗时较短的动作使用将会适得其反。
* <p><u>注意JavaFX 组件不可用,因为它只有一个 UI 线程</u>
*
* @author 夜雨
* @version 2022-10-10 17:05
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IOCAsync {
}

View File

@@ -1,27 +0,0 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 控制反转类使用此注解时将会优先执行实例化,对不存在异步控制反转的类使用不会提升效率。
* <p>使用此注解后,{@link InvokeForInjected} 的方法也会优先于其他类触发
*
* @author 夜雨
* @version 2022-10-10 23:17
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IOCPriority {
/**
* 优先级,默认所有使用此注解的类都会往前挤,除非使用指定等级,数值小的优先执行
*
* @return 优先等级,默认 {@link Integer#MAX_VALUE} / 2非此注解的类的优先级为 {@link Integer#MAX_VALUE}
*/
int value() default Integer.MAX_VALUE / 2;
}

View File

@@ -1,30 +0,0 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 控制反转(方法返回对象),注解在方法上,该方法所在类也必须控制反转到 TimiInject 中,经过此注解的方法返回值也会控制反转到 TimiInject 中并后续执行注入
*
* <p><b><u>注意:注解参数为空时 {@link Inject} 注入对象的变量名需要和此方法名一致</u></b></p>
*
* @author 夜雨
* @version 2022-03-04 23:16
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IOCReturn {
/**
* 对象名称,非空时注入需要明确指定
*
* <p><b><u>为空时注入对象的变量名需要和此方法名一致</u></b></p>
*
* @return 对象名称
*/
String value() default "";
}

View File

@@ -0,0 +1,21 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 引入外部配置类或模块
*
* @author 夜雨
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Import {
/**
* 要引入的配置类或模块类
*/
Class<?>[] value();
}

View File

@@ -6,25 +6,11 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 注入,使用在类变量上,该变量的类需要在 TimiInject 控制反转中才能执行对象注入
*
* <p>注意
* <ul>
* <li><u>如果该类使用 {@link StaticInject} 静态注入,此变量必须为静态变量</u></li>
* <li><u>如果是 {@link IOCReturn} 控制反转的对象,并且控制反转时没有指定名称,此变量名称需要和控制反转方法名一致</u></li>
* </ul>
* 标记用于依赖注入的构造器
*
* @author 夜雨
* @version 2022-03-04 23:15
*/
@Target({ElementType.FIELD})
@Target(ElementType.CONSTRUCTOR)
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
/**
* 注入名称,控制反转明确指定名称时此属性也需要明确指定
*
* @return 注入名称
*/
String value() default "";
}

View File

@@ -1,43 +0,0 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 此注解使用在方法上TimiInject 完成注入后自动执行,对 {@link StaticInject} 和 {@link SuperInject} 有效,方法访问权限无限制。
* <p>注意:{@link StaticInject} 注解类的方法使用此注解时,该方法也必须是静态方法
*
* <pre>
* &#064;Component
* public class Demo {
*
* &#064;InvokeForInjected
* public void hello() {
* System.out.println("hello");
* }
*
* &#064;InvokeForInjected
* public void timiInject() {
* System.out.println("timi-inject");
* }
* }
* </pre>
*
* @author 夜雨
* @version 2022-09-23 22:25
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InvokeForInjected {
/**
* 执行顺序,默认 0数值小的先执行
*
* @return 执行顺序
*/
int value() default 0;
}

View File

@@ -0,0 +1,16 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Bean 初始化后回调方法注解
*
* @author 夜雨
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PostConstruct {
}

View File

@@ -0,0 +1,16 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标记为优先注入的 Bean多实现时
*
* @author 夜雨
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Primary {
}

View File

@@ -0,0 +1,21 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 按名称限定依赖注入
*
* @author 夜雨
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Qualifier {
/**
* Bean 名称
*/
String value();
}

View File

@@ -1,26 +1,22 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 控制反转(资源),注解在类上后该类将被 TimiInject 实例化并控制反转托管,后续执行注入
* 资源层组件注解
*
* @author 夜雨
* @version 2022-03-04 23:16
*/
@Target({ElementType.TYPE})
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Resources {
/**
* 资源名称,非空时注入需要明确执行
*
* @return 资源名称
*/
String value() default "";
/**
* Bean 名称,默认为类名首字母小写
*/
String value() default "";
}

View File

@@ -0,0 +1,21 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Bean 作用域注解
*
* @author 夜雨
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {
/**
* 作用域类型
*/
ScopeType value() default ScopeType.SINGLETON;
}

View File

@@ -0,0 +1,19 @@
package com.imyeyu.inject.annotation;
/**
* Bean 作用域类型
*
* @author 夜雨
*/
public enum ScopeType {
/**
* 单例模式(默认)
*/
SINGLETON,
/**
* 原型模式(每次获取创建新实例)
*/
PROTOTYPE
}

View File

@@ -1,26 +1,22 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 控制反转(服务),注解在类上后该类将被 TimiInject 实例化并控制反转托管,后续执行注入
* 服务层组件注解
*
* @author 夜雨
* @version 2022-03-04 23:16
*/
@Target({ElementType.TYPE})
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
/**
* 服务名称,非空时注入需要明确执行
*
* @return 服务名称
*/
String value() default "";
/**
* Bean 名称,默认为类名首字母小写
*/
String value() default "";
}

View File

@@ -1,27 +0,0 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 静态注入,此类的<u>静态属性</u>将会在控制反转完成后进行注入,<u>此注解的类不会控制反转实例到 TimiInject 中</u>
* <ul>
* <li>{@link InvokeForInjected} 对本注解有效,但必须是静态方法</li>
* </ul>
* <pre>
* &#064;InvokeForInjected
* public static void injected() {
* }
* </pre>
*
* @author 夜雨
* @version 2022-06-24 11:29
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface StaticInject {
}

View File

@@ -1,21 +0,0 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 父级注入,用在控制反转的类上,对控制反转的对象父级的变量也执行注入对象,父级也可以继续使用此注解
*
* <p>*对 {@link StaticInject} 无效
*
* @author 夜雨
* @version 2022-03-04 23:16
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SuperInject {
}

View File

@@ -1,29 +1,21 @@
package com.imyeyu.inject.annotation;
import com.imyeyu.inject.TimiInject;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* TimiInject 注入程序,{@link TimiInject} 核心将基于此注解类的位置(或注解参数)进行包扫描和控制反转
* 标记应用入口类并指定组件扫描路径
*
* @author 夜雨
* @version 2022-03-04 23:32
*/
@Target({ElementType.TYPE})
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TimiInjectApplication {
/**
* 扫描包位置com.imyeyu.inject此包下的所有类将检测控制反转和注入留空则使用注解的类所在包作为扫描位置。
* <p><u>TimiInject 的所有注解在此包扫描范围内有效</u></p>
*
* @return 扫描包位置
*/
String[] value() default {};
/**
* 组件扫描的包路径
*/
String[] value() default {};
}

View File

@@ -1,26 +1,22 @@
package com.imyeyu.inject.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 控制反转(工具),注解在类上后该类将被 TimiInject 实例化并控制反转,后续执行注入
* 工具类组件注解
*
* @author 夜雨
* @version 2023-05-18 00:36
*/
@Target({ElementType.TYPE})
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Util {
/**
* 工具名称,非空时注入需要明确执行
*
* @return 工具名称
*/
String value() default "";
}
/**
* Bean 名称,默认为类名首字母小写
*/
String value() default "";
}

View File

@@ -1,2 +0,0 @@
/** 控制反转和注入注解 */
package com.imyeyu.inject.annotation;