2024. 11. 14. 12:22ㆍSpring Framework/Spring IoC
Using depends-on
Spring의 Java 기반 구성에서는 @DependsOn 어노테이션을 사용하여 빈 간의 초기화 순서를 지정할 수 있습니다.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
@Configuration
public class AppConfig {
@Bean
@DependsOn("manager")
public ExampleBean beanOne() {
ExampleBean exampleBean = new ExampleBean();
exampleBean.setManager(manager());
return exampleBean;
}
@Bean
public ManagerBean manager() {
return new ManagerBean();
}
@Bean
public JdbcAccountDao accountDao() {
return new JdbcAccountDao();
}
@Bean
@DependsOn({"manager", "accountDao"})
public ExampleBean beanOneWithMultipleDependencies() {
ExampleBean exampleBean = new ExampleBean();
exampleBean.setManager(manager());
return exampleBean;
}
}
위 코드에서:
- @DependsOn("manager")를 사용하여 beanOne이 manager 빈이 먼저 초기화된 후에 초기화되도록 지정합니다.
- @DependsOn({"manager", "accountDao"})를 사용하여 beanOneWithMultipleDependencies가 manager와 accountDao 빈이 모두 초기화된 후에 초기화되도록 지정합니다.
Lazy-initialized Beans
@Lazy 어노테이션을 사용하여 lazy-initialized 빈을 정의할 수 있습니다. 또한, 컨테이너 레벨에서 모든 빈을 lazy-initialized로 설정하려면 @Configuration 클래스에 @Lazy 어노테이션을 추가할 수 있습니다.
개별 빈에 대한 lazy initialization
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
@Configuration
public class AppConfig {
@Bean
@Lazy
public ExpensiveToCreateBean lazyBean() {
return new ExpensiveToCreateBean();
}
@Bean
public AnotherBean notLazyBean() {
return new AnotherBean();
}
}
위 코드에서:
- @Lazy 어노테이션을 lazyBean 메서드에 추가하여 해당 빈이 처음 요청될 때까지 초기화되지 않도록 설정합니다.
- notLazyBean은 별도의 어노테이션이 없기 때문에, 기본적으로 즉시 초기화됩니다.
컨테이너 레벨의 lazy initialization
모든 빈을 lazy-initialized로 설정하려면, @Configuration 클래스에 @Lazy 어노테이션을 추가할 수 있습니다:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
@Configuration
@Lazy
public class AppConfig {
@Bean
public ExpensiveToCreateBean lazyBean() {
return new ExpensiveToCreateBean();
}
@Bean
public AnotherBean notLazyBean() {
return new AnotherBean();
}
}
위 코드에서는 @Lazy 어노테이션이 @Configuration 클래스 레벨에 적용되어, 이 클래스 내의 모든 빈이 lazy-initialized 됩니다.
Autowiring Collaborators
Spring에서는 autowiring(자동 주입)을 통해 컨테이너가 빈 간의 의존성을 자동으로 해결하고 주입할 수 있습니다. 이는 구성 컴포넌트간의 관계를 관리하기 위해 ApplicationContext
의 내용을 검사하여 적합한 빈을 찾고 주입하는 방식입니다. Autowiring은 의존성 관리를 단순화하는 강력한 도구로, 특히 개발 초기 단계에서 유용합니다. 그러나 장점, 모드, 제한 사항, 그리고 세밀한 제어 기술이 따릅니다.
Autowiring의 장점
- 구성 설정의 간소화
Autowiring은 의존성을 수동으로 지정하지 않아도 되므로 속성(property)이나 컨스트럭터 아규먼트(argument)를 명시적으로 설정할 필요가 줄어듭니다. 적합한 빈이 컨테이너에 존재하면 자동으로 해결됩니다. - 변화에 대한 적응력
객체가 변화함에 따라 autowiring은 새로운 의존성을 기존 설정을 수정하지 않고도 해결할 수 있습니다. 예를 들어, 클래스에 새로운 의존성이 추가되면 Spring이 자동으로 이를 주입합니다. - 개발 초기 단계에서의 유연성
Autowiring은 설계가 발전하는 초기 개발 단계에서 특히 유용합니다. 명시적 설정이 필요 없으므로 빠르게 프로토타입을 작성할 수 있습니다. 이후, 더 명확하고 안정적인 구성을 위해 명시적 설정으로 전환할 수 있습니다.
Autowiring 모드
Spring은 4가지 autowiring 모드를 제공하며, 각 모드는 XML 구성에서 <bean>
의 autowire
속성을 사용하거나 Java 구성에서 어노테이션으로 설정할 수 있습니다.
1. no
(기본 모드)
- 동작: Autowiring이 비활성화됩니다. 모든 의존성은
<ref/>
등을 사용하여 명시적으로 정의해야 합니다. - 장점:
- 명시적 설정은 더 큰 명확성과 제어를 제공합니다.
- 빈 간의 관계를 구성 파일에 명확히 문서화할 수 있습니다.
- 사용 사례: 명시적 설정이 선호되는 안정적인 대규모 애플리케이션에 적합합니다.
2. byName
- 동작: 속성 이름과 동일한 이름을 가진 빈을 찾아 주입합니다.
예:setMaster()
메서드가 있는 경우, 이름이master
인 빈을 찾아 주입합니다. - 장점:
- 빈 이름을 통해 정확히 일치하는 빈을 선택할 수 있습니다.
- 제한 사항:
- 일치하는 이름의 빈이 없으면 속성이 설정되지 않습니다.
- 일관된 이름 규칙이 필요합니다.
- 사용 사례: 빈 이름 규칙이 엄격히 관리되는 경우.
3. byType
- 동작: 속성의 타입과 동일한 타입의 빈을 찾아 주입합니다.
- 장점:
- 빈 이름에 의존하지 않고 타입을 기준으로 주입을 처리합니다.
- 배열, 컬렉션, Map 타입도 지원합니다.
- 제한 사항:
- 요구되는 타입의 빈이 둘 이상 있으면 치명적 예외가 발생합니다.
- 일치하는 빈이 없으면 속성이 설정되지 않습니다.
- 사용 사례: 타입이 고유한 경우에 적합합니다.
4. constructor
- 동작:
byType
과 유사하지만 생성자 인자에 적용됩니다. Spring은 생성자 인자의 타입에 따라 빈을 주입합니다. - 장점:
- 생성자를 통해 복잡한 의존성을 처리할 수 있습니다.
- 배열, 컬렉션, Map 타입도 지원합니다.
- 제한 사항:
- 요구되는 타입의 빈이 둘 이상 있거나 일치하는 빈이 없으면 치명적 예외가 발생합니다.
- 사용 사례: 생성자 주입을 선호하는 경우에 적합합니다.
특별한 케이스 (byType 및 constructor)
- 컬렉션 및 Map:
- 배열과 특정 타입의 컬렉션은 컨테이너에 존재하는 모든 적합한 빈을 포함합니다.
- Map의 키가
String
일 경우, 키는 빈 이름이 되고 값은 해당 빈 인스턴스가 됩니다.
Autowiring의 한계와 단점
- 모호성(Ambiguity):
여러 빈이 동일한 타입과 일치하면 Spring은 어떤 빈을 주입해야 할지 판단할 수 없습니다. 추가적인 자격 지정(qualifier)이 필요합니다. - 명확성 감소:
Autowiring은 빈 간의 관계를 숨기므로 시스템 구조를 문서화하거나 이해하기 어렵게 만듭니다. - 재정의(Override):
속성(property)이나 생성자 인자(argument)에 명시적으로 정의된 의존성이 Autowiring보다 우선합니다. - 제외(Exclusion):
기본 타입(primitive),String
,Class
, 또는 이들의 배열은 autowiring을 지원하지 않습니다. - 도구 및 문서화 문제:
Spring 컨테이너에서 관계를 문서화하는 도구가 Autowiring으로 생성된 관계를 정확히 반영하지 못할 수 있습니다.
모호성 해결 및 Autowiring 제외
모호성 해결 옵션
- Autowiring 비활성화:
문제가 되는 빈에 대해 명시적 설정을 사용합니다. - Autowiring 제외:
특정 빈을 Autowiring 대상에서 제외하려면 XML에서는autowire-candidate
속성을false
로 설정하고, Java 구성에서는autowireCandidate = false
로 설정합니다.- XML 예제:
<bean id="myBean" class="com.example.MyClass" autowire-candidate="false"/>
- Java 예제:
@Bean(autowireCandidate = false) public MyClass myBean() { return new MyClass(); }
- XML 예제:
- Primary 빈 지정:
우선적으로 주입할 빈을 설정하려면primary = true
로 설정합니다.- XML 예제:
<bean id="primaryBean" class="com.example.MyClass" primary="true"/>
- Java 예제:
@Bean @Primary public MyClass primaryBean() { return new MyClass(); }
- XML 예제:
- Qualifier 사용:
@Qualifier
어노테이션을 사용하여 특정 빈을 지정합니다.
Java 구성의 기본 및 세밀한 제어
Default Candidate와 Autowire Candidate
defaultCandidate
:defaultCandidate = false
로 설정된 빈은 추가적인 자격 지정(qualifier)이 없으면 Autowiring에서 제외됩니다.autowireCandidate
:autowireCandidate = false
로 설정된 빈은 타입 기반 Autowiring에서 완전히 제외됩니다.
패턴 기반 Autowire 후보 선택
XML 구성에서 Autowire 후보를 패턴으로 제한할 수 있습니다.
- XML 예제:
<beans default-autowire-candidates="*Repository"> <bean id="myRepository" class="com.example.MyRepository"/> <bean id="notAutowireable" class="com.example.NotAutowireable"/> </beans>
*Repository
로 끝나는 이름의 빈만 Autowire 대상으로 간주됩니다.
Annotation 기반 구성
@Autowired
, @Primary
, @Qualifier
와 같은 어노테이션을 사용하여 Autowiring을 처리할 수 있습니다. 이는 현대 Spring 애플리케이션에서 일반적입니다.
- 예제:
@Service public class MyService { @Autowired @Qualifier("specificBean") private MyDependency dependency; }
Autowiring은 의존성 관리를 단순화하고 자동화하지만, 모호성과 명확성 부족과 같은 문제를 초래할 수 있습니다. 개발 초기에는 유용하지만, 더 큰 프로젝트에서는 명시적 설정이 선호될 수 있습니다. Exclusion, Primary 빈 지정, Qualifier 사용과 같은 기술을 통해 더 정교하게 제어할 수 있습니다.
'Spring Framework > Spring IoC' 카테고리의 다른 글
Bean Scopes (0) | 2024.11.14 |
---|---|
Method Injection (0) | 2024.11.14 |
Dependencies (0) | 2024.11.14 |
Dependency Injection (0) | 2024.06.11 |
Bean Overview (0) | 2024.06.11 |