Reaching State of Grace in Java Dependency Management.
- Java 100%
| .idea | ||
| build-logic | ||
| dependency-injection | ||
| example | ||
| gradle | ||
| .gitattributes | ||
| .gitignore | ||
| AGENTS.md | ||
| ANNOTATION.md | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| LICENSE | ||
| README.md | ||
| settings.gradle.kts | ||
| verdandi-2.png | ||
| verdandi-3.png | ||
| verdandi-4.png | ||
| verdandi.png | ||
Verdandi
Lightweight, High-Performance JSR-330 Dependency Injection Framework for Modern Java
Verdandi: Lightweight Dependency Injection for Modern Java.
Reaching a State of Grace in Java Dependency Management.
Verdandi는 Java 21+ 환경을 위한 경량 jakarta.inject 기반 의존성 주입(DI) 라이브러리입니다. Fluent API와 리플렉션을 사용해 생성자·필드·메서드 주입, Singleton/Prototype 수명주기, 패키지 스캔을 제공합니다.
Key Features
- JSR-330 (
jakarta.inject) 기반:@Inject,@Singleton,@Named,@Qualifier표준 어노테이션 지원 - Java 21 Virtual Thread 지원: 가상 스레드(Virtual Threads)를 통한 초고속 비동기 빈 초기화 (
InitMode.ASYNC) 지원 - 다양한 주입 방식: 생성자 주입(Constructor), 필드 주입(Field), 메서드/Setter 주입(Method) 전체 지원
- 의존성 기반 자동 등록: annotation이 없는 기본 생성자 클래스도 다른 Bean에 주입되는 경우 자동 등록
- 다형성 타입 바인딩: 상위 클래스 및 구현 인터페이스 조회와
@Named/커스텀 qualifier 지원 - 모호성 검증: 여러 구현체가 qualifier 없이 요청되면
AmbiguousBeanException발생 - Classpath 스캔: 디렉터리와 JAR 패키지 스캔 지원
- 안전한 순환 참조 탐지:
ThreadLocal기반의 인스턴스화 체인 추적을 통해 순환 의존성 발생 시 명확한 예외 제공 - Virtual Thread 초기화:
InitMode.ASYNC,awaitReady(),close()를 통한 초기화 및 자원 관리
Quick Start
1. Dependency 설정
Gradle (build.gradle.kts):
repositories {
maven {
name = "Elex Repository"
url = uri("https://artifacts.elex-project.com/repository/maven/")
}
}
dependencies {
implementation("jakarta.inject:jakarta.inject-api:2.0.1")
implementation("com.elex_project:verdandi:1.0.0")
}
2. Component 정의
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.inject.Singleton;
public interface Engine {
void start();
}
@Singleton
@Named("electricEngine")
public class ElectricEngine implements Engine {
@Override
public void start() {
System.out.println("Electric engine started silently.");
}
}
@Singleton
public class Car {
private final Engine engine;
@Inject
private EngineDiagnostics diagnostics;
@Inject
public Car(@Named("electricEngine") Engine engine) {
this.engine = engine;
}
public void drive() {
engine.start();
System.out.println("Car is running!");
}
}
// annotation이 없어도 Car의 주입 대상이면 자동 등록됩니다.
class EngineDiagnostics {
public void check() { /* ... */ }
}
3. Container 구동 및 빈 사용
Context context = Verdandi.builder()
.scanPackages("kr.pe.elex.example")
.build();
// 빈(Bean) 조회 및 사용
Car car = context.getBean(Car.class);
car.drive();
Context context = Verdandi.builder()
.scanPackages("kr.pe.elex.example")
.initMode(InitMode.ASYNC)
.build();
context.awaitReady();
Car car = context.getBean(Car.class);
car.drive();
context.close();
콜백 기반 초기화도 사용할 수 있습니다.
Verdandi.builder()
.scanPackages("kr.pe.elex.example")
.initMode(InitMode.ASYNC)
.onInit(new InitCallback() {
@Override
public void onComplete(Context context) {
context.getBean(Car.class).drive();
}
@Override
public void onFailure(Throwable cause) {
cause.printStackTrace();
}
})
.build();
Manual Registration
annotation을 추가할 수 없는 클래스는 명시적으로 등록할 수 있습니다.
Context context = Verdandi.builder()
.scanPackages("kr.pe.elex.example")
.registerClasses(ThirdPartyService.class)
.build();
패키지 스캔과 수동 등록이 겹치는 클래스는 중복 등록되지 않습니다.
Bean Resolution Rules
@SingletonBean은 컨테이너에서 하나의 인스턴스를 공유합니다.@Singletonannotation이 없는 Bean은 Prototype으로 생성됩니다.- annotation이 없는 클래스라도 주입 그래프에 포함되고 기본 생성자가 있으면 자동 등록됩니다.
- 동일 타입의 후보가 여러 개면
@Named또는 커스텀@Qualifier를 지정해야 합니다. - 지정한 qualifier가 없거나 요청 타입과 호환되지 않으면
NoSuchBeanException이 발생합니다. - 생성자·필드·메서드 주입의 순환 참조는
CircularDependencyException으로 보고됩니다.
Advanced Features
Custom Qualifier
커스텀 퀄리파이어 어노테이션을 선언하여 동일 타입의 다중 구현체를 안전하게 구분하여 주입할 수 있습니다.
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface Fast {}
@Fast
public class V8Engine implements Engine { ... }
@Singleton
public class SportsCar {
@Inject
@Fast
private Engine engine; // V8Engine이 주입됨
}
Architecture Overview
Verdandi는 다음과 같은 핵심 모듈로 명확히 역할이 분리되어 설계되었습니다.
+-----------------------------------------------------------------------+
| Verdandi (Facade) |
+-----------------------------------------------------------------------+
|
v
+-----------------------+ +-----------------------+ +-----------------------+
| PackageScanner | --> | BeanRegistry | <-- | Injector |
| (Classpath Discovery)| | (Metadata Store) | | (Di Engine / VT) |
+-----------------------+ +-----------------------+ +-----------------------+
Verdandi(Facade): 컨테이너의 설정 및 빌드를 담당하는 Fluent Builder API.PackageScanner: 디렉터리/JAR에서 클래스를 발견하고 annotation root 및 주입 그래프의 기본 생성자 의존성을 분석.BeanRegistry: 타입별 후보 목록과 qualifier 이름을 원자적으로 관리하고 다중 후보를 보존.Injector: 스코프 전략(Singleton/Prototype) 및 순환 참조를 검증하며 인스턴스를 생성하고 주입을 실행하는 핵심 엔진.
License
This project is licensed under the Apache License 2.0.
Copyright © 2026 Elex Project. All rights reserved.
