2024. 6. 11. 17:28ㆍSpring Framework/Spring IoC
의존성 주입(DI) 은 객체가 자신이 필요로 하는 의존성(즉, 함께 동작할 다른 객체들)을 다음과 같은 방식으로만 정의하는 과정입니다:
- 생성자 아규먼트(Constructor arguments)
- 팩토리 메서드의 아규먼트(Factory method arguments)
- 객체가 생성된 후 설정되는 프로퍼티(Properties)
이후 Spring IoC 컨테이너는 해당 빈(Bean)을 생성할 때 이 의존성들을 주입(inject)합니다.
이러한 과정은 본질적으로 역제어(Inversion of Control, IoC) 의 개념을 따릅니다.
- 이름 그대로, 의존성의 생성이나 위치를 스스로 제어하는 것이 아니라, 컨테이너가 대신 제어하게 되는 구조입니다.
- 예전에는 객체가 필요한 의존성을 직접 생성하거나, Service Locator 패턴을 이용해 직접 위치를 찾아야 했지만, DI는 이를 반대로 뒤집어 컨테이너가 주입해주는 방식입니다.
✅ DI 원칙의 효과
- DI 원칙을 적용하면 코드가 더 깔끔해지고, 결합도가 낮아집니다.
- 객체는 의존성을 직접 찾지 않으며, 의존성의 위치나 클래스에 대해 알 필요도 없습니다.
- 그 결과:
- 클래스가 더 테스트하기 쉬워집니다.
- 특히 의존성이 인터페이스나 추상 클래스에 기반할 경우, 테스트 시 Stub 또는 Mock 구현체를 사용하기가 용이합니다.
✅ DI의 주요 두 가지 방식
- 생성자 기반 의존성 주입(Constructor-based Dependency Injection)
- 세터 기반 의존성 주입(Setter-based Dependency Injection)
✅ Constructor-based Dependency Injection
생성자 기반 DI(Constructor-based DI) 는 컨테이너가 여러 개의 아규먼트를 가진 생성자를 호출하여 의존성을 주입하는 방식입니다. 여기서 각 아규먼트는 하나의 의존성을 나타냅니다.
특정 아규먼트를 전달하여 정적 팩토리 메서드(static factory method) 를 호출해 빈(Bean)을 생성하는 것도 거의 동일한 방식으로 취급됩니다. 따라서, 이 설명에서는 생성자 아규먼트와 정적 팩토리 메서드 아규먼트를 동일하게 다룹니다.
다음 예제는 오직 생성자 주입을 통해서만 의존성을 주입받는 클래스를 보여줍니다.
public class SimpleMovieLister {
// the SimpleMovieLister has a dependency on a MovieFinder
private final MovieFinder movieFinder;
// a constructor so that the Spring container can inject a MovieFinder
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// business logic that actually uses the injected MovieFinder is omitted...
}
- 이 클래스에는 특별한 점이 없습니다.
- POJO (Plain Old Java Object) 이며,
- Spring 컨테이너에 특화된 인터페이스, 부모 클래스, 애노테이션 등에 전혀 의존하지 않습니다.
✅ Constructor-based Dependency Injection 장단점
구분 | 내용 |
장점 | |
필수 의존성 보장 | 생성자 호출 시점에 모든 필수 의존성이 주입되므로, 주입 누락 시 컴파일 오류(또는 초기화 오류)로 바로 확인 가능 |
불변성(Immutable) 보장 | final 필드와 함께 사용하면, 객체가 생성된 이후 의존성이 변경될 수 없도록 강제 가능 |
테스트 용이성 | 외부에서 의존성을 주입하기 때문에 테스트 시 Mock, Stub 주입이 간편 |
명확한 의존성 표현 | 클래스가 어떤 의존성을 필요로 하는지 생성자 시그니처만 봐도 알 수 있음 |
순환 참조 조기 감지 | 컨테이너가 인스턴스화 시점에 순환 참조를 빠르게 감지하고 예외 발생 |
단점 | |
의존성 수 증가 시 가독성 저하 | 의존성이 많아지면 생성자 아규먼트가 많아져 코드 가독성이 나빠짐 (Bad Smell: 클래스가 너무 많은 책임을 가짐) |
순환 참조 대응 어려움 | 순환 참조 상황에서 생성자 기반 DI는 해결이 불가능 (Setter-based DI로 우회해야 함) |
선택적 의존성 대응 불편 | 선택적 의존성을 주입받기 어렵고, 기본값을 주는 등의 처리가 번거로움 |
✅ Spring의 Constructor-based DI 과정 흐름도

🔍 핵심 요점:
단계 | 설명 |
[1] | XML, Java Config, @Component 등으로 빈 정의 |
[2] | 내부적으로 BeanDefinition 생성 (빈의 설계도 역할) |
[3] | ApplicationContext 초기화 |
[4] | Constructor Injection 수행 (필수 의존성 모두 주입) |
[5] | Bean 인스턴스화 완료 |
[6] | 초기화 콜백(@PostConstruct 등) |
[7] | 클라이언트가 빈을 주입받아 사용 |
✅ Constructor Argument Resolution
교재의 설명은 XML 기반 구성 메타데이터에 관한 것이기 때문에,
자바 또는 어노테이션 기반 구성 메타데이터에서는 해당 사항이 없습니다.
그러므로 어노테이션 기반 구성 메타데이터 예제로 대체하겠습니다.
package x.y;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public ThingTwo beanTwo() {
return new ThingTwo();
}
@Bean
public ThingThree beanThree() {
return new ThingThree();
}
@Bean
public ThingOne beanOne(ThingTwo beanTwo, ThingThree beanThree) {
return new ThingOne(beanTwo, beanThree);
}
}
✅ Constructor argument type matching
xml 기반 메타데이터에 국한된 내용이라 생략하도록 하겠습니다
package examples;
public class ExampleBean {
// Number of years to calculate the Ultimate Answer
private final int years;
// The Answer to Life, the Universe, and Everything
private final String ultimateAnswer;
public ExampleBean(int years, String ultimateAnswer) {
this.years = years;
this.ultimateAnswer = ultimateAnswer;
}
}
@Configuration
public class AppConfig {
// <bean id="exampleBean" class="examples.ExampleBean">
// <constructor-arg type="int" value="7500000"/>
// <constructor-arg type="java.lang.String" value="42"/>
// </bean>
@Bean
public ExampleBean exampleBean() {
String str = "42";
return new ExampleBean(7500000, str);
}
}
✅ Constructor argument index
xml 기반 메타데이터에 국한된 내용이라 생략하도록 하겠습니다
✅ Constructor argument name
다음은 resources 디렉토리에 있는 example.properties 파일입니다.
example.years=42
example.ultimateAnswer=Life, Universe and Everything
다음은 AppConfig에 추가된 configure 빈입니다.
@Configuration
@ComponentScan({"com.intheeast.ioc.dependencies.dependencyinjection"})
public class AppConfig {
// Define MovieFinder bean
@Bean
public MovieFinder movieFinder() {
return new SimpleMovieFinder();
}
// Define SimpleMovieLister bean
@Bean
public SimpleMovieLister movieLister(MovieFinder movieFinder) {
SimpleMovieLister movieLister = new SimpleMovieLister();
movieLister.setMovieFinder(movieFinder); // Setter-based DI
return movieLister;
//return new SimpleMovieLister(movieFinder);
}
// @Value 어노테이션으로 주입되려면, 반드시 다음 configure가 필요함!
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer.setLocation(new org.springframework.core.io.ClassPathResource("example.properties"));
return configurer;
}
}
다음은 컨스트럭터 파라미터의 아규먼트로 properties 파일에 정의된 값을 주입하는 예제 코드입니다
@Component
public class ExampleBean {
private final int years;
private final String ultimateAnswer;
public ExampleBean(
@Value("${example.years}") int years,
@Value("${example.ultimateAnswer}") String ultimateAnswer) {
this.years = years;
this.ultimateAnswer = ultimateAnswer;
}
// Getter 생략
}
✅ 생성자 기반 DI (Constructor Injection) 예제
Spring이 가장 권장하는 방식이며, 불변 객체를 만들고, 필수 의존성을 강제할 수 있음
@Component
public class Repository {
public void save() {
System.out.println("Data saved!");
}
}
@Component
public class Service {
private final Repository repository;
// 생성자를 통한 의존성 주입
@Autowired
public Service(Repository repository) {
this.repository = repository;
}
public void performAction() {
repository.save();
}
}
📌 특징
✅ 필수 의존성을 강제할 수 있음
✅ 객체를 불변(immutable)하게 유지할 수 있음
✅ @Autowired 생략 가능 (Spring 4.3 이상)
✅ Setter-based Dependency Injections
의존성을 선택적으로 주입할 때 사용되며, 초기화 이후 변경이 가능함.
컨테이너가 아규먼트 없는 컨스트럭터나 아규먼트 없는 static 팩토리 메서드를 호출하여, 빈을 인스턴스화한 후 빈에서 세터 메서드를 호출하여 수행됩니다.
@Component
public class Service {
private Repository repository;
// 기본 생성자
public Service() {}
// Setter 메서드를 통한 의존성 주입
@Autowired
public void setRepository(Repository repository) {
this.repository = repository;
}
public void performAction() {
repository.save();
}
}
📌 특징
✅ 선택적 의존성 주입 가능
✅ 객체 생성 후 의존성을 변경 가능
❌ 객체의 불완전한 상태(incomplete state) 발생 가능
✅ 세터 기반 DI 핵심 개념 요약 테이블
구분 | 설명 | 핵심 포인트 |
DI 방식 | ApplicationContext는 생성자 기반 주입(Constructor DI)과 세터 기반 주입(Setter DI)을 모두 지원 | 둘 다 가능, 혼합 사용 가능 |
세터 DI 추가 주입 | 생성자 DI 이후에도 세터를 통해 추가 주입 가능 | 보완적 DI 지원 |
BeanDefinition | 빈(Bean)의 메타데이터(설정 정보)를 표현하는 내부 구조체 | Spring 내부에서 핵심 |
PropertyEditor | 속성(Property)의 형식 변환을 위한 도구 (예: String → Integer) | 타입 변환기 역할 |
일반 사용자 관점 | 직접 BeanDefinition, PropertyEditor를 다루지 않음 | XML, @Component, @Bean 방식 사용 |
내부 처리 과정 | XML, @Component, @Bean 소스 → 내부적으로 BeanDefinition 으로 변환 후 IoC 컨테이너 로딩 | 개발자는 신경쓰지 않아도 됨 |
✅ Sprng Bean 구성과 주입의 흐름 (개념도)

🔍 설명:
- 개발자는 XML, @Component, @Bean 방식으로 빈을 정의합니다.
- Spring은 이 정의들을 내부적으로 BeanDefinition 객체로 변환합니다.
- property의 값 타입이 필요한 경우 PropertyEditor를 통해 변환 작업이 이뤄집니다.
- 완성된 BeanDefinition 정보를 바탕으로 ApplicationContext가 빈을 생성하고 의존성 주입(DI)을 수행합니다.
- 생성자 기반 DI
- 세터 기반 DI (필요 시 보완적으로 추가 주입 가능)
✅ 시각적 한눈 정리
개발자 입장 | 내부 | 동작 결과 |
XML, @Component, @Bean으로 빈 정의 | BeanDefinition으로 변환 | IoC 컨테이너 초기화 |
@Value, constructor-arg 값 등 | PropertyEditor로 타입 변환 | 알맞은 타입으로 주입 |
생성자 방식, 세터 방식 혼합 사용 | DI 수행 | 실제 빈(Bean) 생성 및 주입 완료 |
✅ 생성자 기반 주입(Constructor-based DI) vs 세터 기반 주입(Setter-based DI)?
생성자 기반 주입과 세터 기반 주입은 혼합하여 사용할 수 있기 때문에, 일반적으로 다음과 같은 원칙을 따르는 것이 좋습니다
필수 의존성은 생성자(Constructor)를 통해 주입하고, 선택적(Optional) 의존성은 세터(Setter)나 구성 메서드를 통해 주입하는 것이 좋습니다.
@Autowired 애노테이션을 세터 메서드에 사용하면 해당 속성을 필수 의존성으로 만들 수 있지만, 생성자 주입과 아규먼트에 대한 프로그래밍적 검증(유효성 검사)을 병행하는 것이 더 바람직합니다.
✅ 스프링 팀의 권장 사항 (생성자 주입 선호)
- Spring 팀은 생성자 주입(Constructor Injection)을 권장합니다.
- 이유:
- 불변(Immutable) 객체로 애플리케이션 컴포넌트를 구현할 수 있습니다.
- 필수 의존성이 null이 아님을 보장할 수 있습니다.
- 생성자 주입을 통해 항상 완전히 초기화된 상태의 객체를 클라이언트(호출하는 코드)에게 반환할 수 있습니다.
또한, 생성자 아규먼트가 과도하게 많다면 그것은 "좋지 않은 코드 냄새(Bad Code Smell)" 로 간주됩니다.
→ 이는 해당 클래스가 너무 많은 책임을 지고 있음을 의미하며, 관심사의 분리(Separation of Concerns) 를 위해 리팩토링이 필요하다는 신호입니다.
✅ 세터 주입의 적절한 활용
- 세터 주입은 디폴트 값(Default Value)을 가질 수 있는 선택적 의존성(옵션) 에 주로 사용해야 합니다.
- 만약 필수 의존성을 세터로 주입한다면, 그 의존성을 사용할 때마다 null 체크를 직접 수행해야 하는 불편함이 발생합니다.
- 세터 주입의 장점:
- 세터 메서드를 통해 해당 클래스의 객체를 나중에 재설정(Reconfiguration)하거나 재주입(Re-injection)하는 것이 용이합니다.
- 특히 JMX MBean을 통한 관리와 같은 경우에는 세터 주입이 유용한 사례가 됩니다.
✅ 상황에 맞게 선택하라
- 특정 클래스에 적합한 방식(DI 스타일)을 상황에 따라 선택하는 것이 좋습니다.
- 때로는 서드파티(Third-party) 클래스와 같이 소스 코드를 수정할 수 없는 경우, 선택의 여지가 없습니다.
- 예를 들어, 서드파티 클래스가 세터 메서드를 제공하지 않는다면 생성자 주입(Constructor Injection) 만이 유일한 DI 방법일 수 있습니다.
✅ Dependency Resolution Process
1️⃣ 컨테이너의 의존성 해결 절차
- ApplicationContext는 모든 빈(Bean)을 설명하는 구성 메타데이터(Configuration Metadata) 로 생성되고 초기화됩니다.
- 구성 메타데이터는 XML, 자바 코드, 애노테이션을 통해 지정할 수 있습니다.
- 각 빈(Bean)에 대한 의존성은 프로퍼티(Property), 생성자 아규먼트(Constructor Argument), 또는 정적 팩토리 메서드의 아규먼트 형태로 표현됩니다.
- (정적 팩토리 메서드를 사용하는 경우 생성자 대신 사용)
- 이 의존성들은 빈이 실제로 생성될 때 주입됩니다.
- 각 프로퍼티나 생성자 아규먼트는 실제 값(리터럴 값) 을 설정하거나, 컨테이너 내의 다른 빈에 대한 참조(Reference) 를 가리킵니다.
- 값으로 주어지는 경우에는, 설정된 형식에서 프로퍼티나 생성자 아규먼트의 실제 타입으로 변환됩니다.
- 디폴트로 Spring은 문자열 형식으로 제공된 값을 int, long, String, boolean 등 모든 기본 내장 타입으로 변환할 수 있습니다.
2️⃣ 빈의 검증과 생성 시점
- Spring 컨테이너는 생성 시 각 빈의 구성을 검증합니다.
- 그러나 빈의 프로퍼티들은 빈이 실제로 생성될 때까지 설정되지 않습니다.
- 싱글톤(Singleton) 범위로 설정된 빈(기본값)은 컨테이너가 생성될 때 함께 생성됩니다.
- 기타 범위(Scope)는 요청 시점(Lazy)까지 생성되지 않습니다.
빈이 생성되면서 그 빈의 의존성들, 또 그 의존성들의 의존성들(Dependency Graph)까지 함께 생성되고 주입됩니다.
- 의존성 해결 과정에서 발생하는 불일치(예: 참조 오류)는 해당 빈이 처음 생성되는 시점에 발생할 수 있습니다.

Spring은 일반적으로 알아서 올바르게 동작한다고 믿어도 됩니다.
Spring은 존재하지 않는 빈에 대한 참조나 순환 참조(circular dependencies) 와 같은 구성 오류를 컨테이너 로드 시점에 감지합니다.
Spring은 속성(property) 설정과 의존성 주입을 가능한 한 늦게, 즉 빈이 실제로 생성되는 시점에 수행합니다.
이로 인해 Spring 컨테이너가 정상적으로 로드된 이후에도, 객체를 요청하는 시점에
그 객체나 해당 객체의 의존성을 생성하는 과정에서 예외가 발생할 수 있습니다.
예를 들면, 필수 속성이 누락되었거나 잘못된 값이 설정되어 빈이 예외를 발생시키는 경우입니다.
이와 같은 구성 오류가 늦게 드러나는 문제(delayed visibility of configuration issues) 를 방지하기 위해,
Spring의 ApplicationContext 구현체는 기본적으로 싱글톤 빈을 선 인스턴스화(pre-instantiate) 합니다.
이는 실제로 필요하기 전 미리 빈을 생성하는 것이므로, 초기 메모리 및 시간 측면에서 다소 비용이 발생하지만,
컨테이너 생성 시점에 이러한 오류를 미리 발견할 수 있습니다.
이러한 기본 동작은 변경할 수 있으며,
싱글톤 빈이 지연 초기화(lazy initialization) 되도록 설정하여, 실제 사용 시점까지 생성을 미룰 수도 있습니다.
✅ 순환 참조 (Circular Dependencies)
⚠ 예제: 생성자 주입으로 인한 순환 의존성 발생
@Component
public class A {
private B b;
@Autowired
public void setB(B b) {
this.b = b;
}
}
@Component
public class B {
private final A a;
@Autowired
public B(A a) {
this.a = a;
}
}
- 생성자 주입(Constructor Injection)을 주로 사용하는 경우, 해결할 수 없는 순환 참조 상황이 발생할 수 있습니다.
예시:
- 클래스 A가 생성자 주입으로 클래스 B를 요구하고,
- 클래스 B가 생성자 주입으로 클래스 A를 요구하는 경우.
- 이처럼 서로가 서로를 요구하는 상황에서 Spring IoC 컨테이너는 런타임에 BeanCurrentlyInCreationException 예외를 던집니다.
해결 방법:
- 일부 클래스를 수정하여 세터 주입(Setter Injection) 으로 변경.
- 혹은 생성자 주입 대신 세터 주입만 사용하는 것도 가능.
- (권장되지는 않지만, 세터 주입 방식으로 순환 참조를 해결할 수 있습니다.)
✅ 해결 방법 1: 세터 주입으로 변경
@Component
public class A {
private B b;
@Autowired
public void setB(B b) {
this.b = b;
}
}
@Component
public class B {
private final A a;
@Autowired
public B(A a) {
this.a = a;
}
}
📌 왜 해결되는가?
- 세터 주입은 객체가 완전히 생성된 후 주입됨
- Spring이 A와 B 중 하나를 먼저 생성할 수 있음
✅ 해결 방법 2: @Lazy 사용
@Component
public class A {
private final B b;
@Autowired
public A(@Lazy B b) {
this.b = b;
}
}
📌 @Lazy를 사용하면?
✅ B의 객체 생성을 지연 → 즉시 객체를 만들지 않고 필요할 때 생성
✅ 순환 참조 문제 해결
주의:
- 순환 참조가 있는 경우, 두 빈(A, B)이 서로에게 주입되면서 아직 완전히 초기화되지 않은 상태에서 상대에게 주입 되는 "닭이 먼저냐, 달걀이 먼저냐" 상황이 발생합니다.
✅ Spring의 처리 방식
- Spring은 참조 오류나 순환 참조 같은 구성 문제를 감지합니다.
- Spring은 빈의 프로퍼티 설정과 의존성 해결을 가장 늦은 시점(Lazy)까지 미룹니다.
- 즉, 빈이 실제로 생성될 때 해결합니다.
그래서 컨테이너가 정상적으로 로드되었더라도, 실제로 빈을 요청할 때 예외가 발생할 수 있습니다.
예를 들어, 빈 생성 시점에 누락된 속성값으로 인해 예외가 발생할 수 있습니다.
이러한 지연된 오류 노출(Delayed Visibility)을 줄이기 위해:
- ApplicationContext는 기본적으로 싱글톤 빈을 미리 인스턴스화(pre-instantiate) 합니다.
- 메모리와 초기화 비용이 조금 들더라도, 컨테이너 초기화 시점에 문제를 미리 발견할 수 있습니다.
- 원한다면 이 기본 동작을 변경하여 싱글톤 빈도 지연 초기화(lazy-initialize) 하도록 설정할 수 있습니다.
✅ 순환 참조가 없는 경우의 동작
- 순환 참조가 없는 경우, 하나 이상의 협력 빈(collaborating beans)이 다른 빈에 주입될 때,
- 각 협력 빈은 완전히 구성된 상태로 주입됩니다.
- 예를 들어, 빈 A가 빈 B를 의존하는 경우,
- Spring IoC 컨테이너는 먼저 빈 B를 완전히 생성 및 초기화하고 (의존성 주입 포함),
- 이후 빈 A의 세터 메서드를 호출하여 빈 B를 주입합니다.
- 즉, 주입되는 빈은:
- 인스턴스화되고 (싱글톤이며 선 인스턴스화가 아닐 경우, 이 시점에 생성),
- 모든 의존성이 주입되고,
- 초기화 메서드(예: 설정된 init 메서드, InitializingBean의 afterPropertiesSet 등)가 호출된 이후에야 주입됩니다.
✅ 필드 기반 DI (Field Injection)
필드에 @Autowired
를 사용하여 직접 주입하는 방식
@Component
public class Service {
@Autowired
private Repository repository;
public void performAction() {
repository.save();
}
}
📌 특징
✅ 코드가 간결함
❌ 의존성이 명확하지 않음 → 테스트 및 유지보수 어려움
❌ 순환 참조(Circular Dependency) 문제 발생 가능
❌ Spring 컨테이너 없이 객체 생성 불가
🚀 Spring 공식 문서에서도 "필드 주입은 권장되지 않음"
💡 대신 생성자 주입을 사용하는 것이 더 좋은 방법
✅ DI 방식 비교 및 선택 기준
DI 방식 | 특징 | 장점 | 단점 |
---|---|---|---|
생성자 주입 (권장) | 생성자를 통해 의존성 주입 | ✅ 필수 의존성 강제 ✅ 객체 불변성 유지 |
❌ 필수 의존성 없는 경우 다소 불편 |
세터 주입 | Setter 메서드를 통해 주입 | ✅ 선택적 의존성 주입 가능 ✅ 의존성 변경 가능 |
❌ 객체의 불완전한 상태 가능 |
필드 주입 (비추천) | @Autowired 로 직접 주입 |
✅ 코드가 간결함 |
📌 권장하는 DI 방식
- 필수 의존성은 생성자 주입 (
@Autowired
생략 가능) - 선택적 의존성은 세터 주입
- 필드 주입은 추천되지 않음
🎯 Summary (요약)
🔹 Dependency Injection(DI) 은 객체 간 결합도를 줄이고, 유지보수성과 테스트 용이성을 높이는 핵심 개념
🔹 Spring의 DI 방식
✅ 생성자 주입 (권장) → 불변성 유지, 필수 의존성 강제
✅ 세터 주입 → 선택적 의존성 주입 가능
❌ 필드 주입 (비추천) → 유지보수 어려움, 순환 참조 문제 발생
🔹 순환 의존성(Circular Dependency) 해결 방법
✅ 세터 주입으로 변경
✅ @Lazy
애노테이션 사용
🚀 DI를 적절하게 활용하면 유지보수성이 높은 확장 가능한 애플리케이션을 개발할 수 있습니다! 🎯
출처: https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html
Dependency Injection :: Spring Framework
Constructor-based DI is accomplished by the container invoking a constructor with a number of arguments, each representing a dependency. Calling a static factory method with specific arguments to construct the bean is nearly equivalent, and this discussion
docs.spring.io
'Spring Framework > Spring IoC' 카테고리의 다른 글
Using depends-on, Lazy-initialized Beans, Autowiring Collaborators (0) | 2024.11.14 |
---|---|
Dependencies (0) | 2024.11.14 |
Bean Overview (0) | 2024.06.11 |
Using @Autowired (0) | 2023.12.10 |
Dependencies and Configuration in Detail (0) | 2023.12.10 |