이전 포스팅에서 이어집니다.
의존성 주입(Dependency Injection) (1 / 2)
의존성 주입 객체가 필요로 하는 어떤 것을 외부에서 전달해주는 행위를 말하며, 포괄적인 의미로서 두 객체 간의 관계를 외부에서 결정해주는 디자인 패턴을 의미합니다. 예시(의존성 주입이
doinitright.tistory.com
@Autowired
다양한 타입의 의존성을 자동으로 처리해 줄 수 있는 Spring 프레임워크 지원하는 어노테이션입니다.
@Autowired는 "인터페이스를 선언한 변수에 자동적으로 그 인터페이스를 재정의한 객체를 주입시킨다"는 의미의 어노테이션입니다.
그러나, @Autowired는 생성자, Setter, 필드 등에 사용될 수 있으므로 이보다는 더 쉬운 의미로 접근하고자 한다면
"@Autowired는 의존성이 있는 객체 ↔ 객체를 매칭시켜준다" 라고 이해하시면 편합니다.
그 과정에서 전제 조건은 두 가지가 있습니다.
- @Autowired를 사용하는 (생성자, Setter, 필드)를 내부에 가지고 있는 객체가 스프링 빈에 등록되어 있어야 하는 것
- @Autowired를 사용해 (생성자, Setter, 필드)를 통해 주입시킬 인자 객체가 스프링 빈에 등록되어 있어야 하는 것
스프링 빈(Spring Bean)?
스프링 차원에서 관리하는 객체로, "공유 객체" 의 의미와 근접합니다.
Bean은 스프링 IOC 컨테이너에 의해 재사용 가능한 자바 객체입니다.
일반적인 자바 객체의 경우 앱 실행 내에서 사용이 중단될 시 일정 흐름에 따라 가비지 컬렉션에 의해 청소됩니다.
그러나, 스프링 빈에 등재된 객체인 경우 그 가치 존재를 설계자가 인정함으로써 재사용 가능한 형태로 대기시키며, 호출될 시 필요에 의해 이를 주입시킵니다.
스프링 빈으로 클래스를 등재하는 방법은 클래스 상단에 @Component, @Service, @Repository, @Service 등 중 하나를 명시하는 것입니다.
해당 어노테이션 중 하나를 선언하면 앱 구동 시 스프링이 클래스의 객체를 자동 생성해 Bean 객체로 관리합니다.
기존 예시를 활용한 @Autowired 이해
class Eat {
private final Meat meat;
// 생성자 주입
public Eat(Meat meat){
this.meat = meat
}
class Meat{}
class Beef extends Meat{}
class Pork extends Meat{}
저번 포스팅에서 생성자를 활용한 의존성 주입에 대해 알아봤고, 위가 해당 예시입니다.
Eat 클래스는 Meat을 생성자를 통해 의존성 주입을 받고 있습니다.
@AutoWired를 통해 고유한 Meat 객체 meat를 자동적으로 Eat 클래스의 의존성으로 주입을 시키기 위해서는
앞서 말한 두가지 전제조건이 필요합니다. 바로, Meat과 Eat을 스프링 빈 객체로 등록시키는 것입니다.
@Component
class Eat {
private final Meat meat;
// 생성자 주입
public Eat(Meat meat){
this.meat = meat
}
@Component
class Meat {}
위 과정을 거칠 시 스프링 IOC 컨테이너에서는 두 클래스로 인해 생성되는 객체를 프로그램 실행 시 자동으로 스프링 빈의 고유 객체로 인식하고 저장하게 됩니다.
그 이후, 자동적으로 Eat 객체에 주입시킬 Meat 객체를 스프링 빈 객체 중에서 자동으로 찾아서 이를 연결시켜 주기 위한 과정에서 @Autowired가 사용됩니다.
@Component
class Eat {
private final Meat meat;
@Autowired
public Eat(Meat meat){
this.meat = meat
}
위와 같이 생성자에 @Autowired를 붙이게 되면,
@Component 등을 붙여 스프링 빈 객체로 관리하고 있는 Eat 객체와 Meat 객체를 자동으로 찾아 이를 연결시켜 줍니다.
동일한 타입의 빈 객체가 여러 개면? → @Qualifier를 사용한다
@Component
class Meat {}
private final Meat Beef = new Meat();
private final Meat Pork = new Meat();
private final Meat Chicken = new Meat();
이 과정에서 의문점이 생길 수 있습니다.
"그렇다면 동일한 타입인 Meat 객체가 여러개 생긴다면 @AutoWired를 통해 자동으로 연결되는 객체는 무엇일까?"
이런 문제를 해결하기 위해 @Qualifier 어노테이션을 사용할 수 있습니다.
@Qualifier (식별자)
사용할 의존 객체를 선택할 수 있도록 해주는 어노테이션입니다.
@Autowired로 인해 적용된 주입 대상에 설정함으로써 주입할 빈 객체를 지정할 수 있습니다.
@Component
class Eat {
private final Meat meat;
@Autowired
public Eat(@Qualifier("chicken") Meat meat){
this.meat = meat
}
위는 @Qualifier를 활용해 주입 대상 Meat 객체를 chicken으로 설정하는 예제입니다.
@Qualifier를 통해 주입 대상을 설정해 줌으로써, 빈 객체를 주입하는 과정에서 객체 간의 충돌을 방지할 수 있습니다.
만약 각 타입의 빈 객체가 하나만 존재한다면,
@Qualifier를 통한 식별자 설정 없이도 @Autowired 만을 사용해도 자동으로 연결이 됩니다.
생성자 주입 시 @Autowired를 생략해도 되는 경우
@Component
@RequiredArgsConstructor
class Eat {
private final Meat meat;
// @Autowired
// public Eat(Meat meat){
// this.meat = meat
// }
그거 알고 계신가요? @RequiredArgsConstructor를 사용하면 생성자가 생성이 됩니다.
Spring IOC 컨테이너는 Bean을 통해 등록되어 있는 두 객체가 생성자 주입을 통해 의존 관계가 성립이 될 시,
@Autowired를 생략해도 @Autowired처럼 의존성을 주입해 주는 기능을 제공합니다.
이를 "암시적 생성자 주입 기능"이라고 정의합니다.
@RequiredArgsConstructor를 사용하면 이 "암시적 생성자 주입 기능"으로 인해 @Autowired가 작동하게 됩니다.
암시적 생성자 주입(Implicit Constructor Injection)
생성자가 하나뿐이고 해당 생성자의 매개변수가 모두 빈으로 등록되어 있으면 암시적으로 생성자가 주입됩니다.
(@Autoired가 생략되어 있어도 @Autowired가 작동된다는 뜻)
@Component
@RequiredArgsConstructor
class Eat {
private final Meat meat;
private final Veg veg;
// @Autowired
// public Eat(Meat meat, Veg veg){
// this.meat = meat;
// this.veg = veg;
// }
@Component
class Veg {}
@Component
class Meat{}
위 예시 같은 경우도 Veg와 Meat 클래스가 모두 빈 객체로 선언되어 있기 때문에,
@Autowired를 생략해도 자동적으로 의존성 주입이 동작하겠습니다.
@Autowired를 활용한 Setter 주입과 필드 주입 예시
// Eat 클래스 with 세터 주입
@Component
public class Eat {
private final Meat meat;
@Autowired
public void setMeat(Meat meat) {
this.meat = meat;
}
}
Setter 주입
// Eat 클래스 with 필드 주입
@Component
public class Eat {
@Autowired
private final Meat meat;
}
필드 주입
@Autowired에 대해 알아보았습니다.
'DEV > Spring' 카테고리의 다른 글
[Spring] @Configuration을 활용한 @Bean 등록 방법 (0) | 2023.11.23 |
---|---|
[Spring] @RequestParam의 이해 (0) | 2023.11.21 |
[Spring] 의존성 주입(Dependency Injection)의 정의와 설명 (1 / 2) (0) | 2023.11.16 |
[Spring Boot] java 기반 Spring Boot 프로젝트 생성 방법 (0) | 2023.10.12 |
[Spring Boot] ORM, JPA의 개념과 JPA 사용 설정 (0) | 2023.09.13 |