생성자 주입, setter 주입, 필드 주입 메서드 주입 4가지 방법이 존재한다.
@Autowired는 의존성을 자동으로 주입할 때 사용하는 어노테이션이다.
기본적으로 주입할 대상이 없으면 오류가 발생한다(required = true)
의존관계를 자동으로 주입할 객체가 Spring Bean으로 등록되어 있어야 @Autowired로 주입이 가능하다.
1. 생성자 주입
최초에 한번 생성된 후 값이 수정되지 못한다.
public interface MyService {
void doSomething();
}
// Spring Bean으로 등록
@Service
public class MyServiceImpl implements MyService {
@Override
public void doSomething() {
System.out.println("MyServiceImpl 메서드 호출");
}
}
// 생성자 주입 방식
@Component
public class MyApp {
// 필드에 final 키워드 필수! 무조건 값이 있도록 만들어준다.(필수)
private final MyService myService;
// 생성자를 통해 의존성 주입, 생략 가능
@Autowired
public MyApp(MyService myService) {
this.myService = myService;
}
public void run() {
myService.doSomething();
}
}
@ComponentScan(basePackages = "com.example.springdependency.test")
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
// 등록된 MyApp 빈 가져오기
MyApp myApp = context.getBean(MyApp.class);
// 빈 메서드 호출
myApp.run();
}
}
생성자가 하나일땐 @Autowired를 생략해도 된다.
2. Setter 주입
@Component
public class MyApp {
private MyService myService;
// Setter 주입
@Autowired
public void setMyService(MyService myService) {
this.myService = myService;
}
public void run() {
myService.doSomething();
}
}
선택하거나 변경 가능한 의존관계에 사용한다.
3. 필드 주입
@Component
public class MyApp {
@Autowired
private MyService myService; // 필드에 직접 주입
public void run() {
myService.doSomething();
}
}
코드는 간결하나 Spring이 없으면 사용할 수 없다.
외부에서 myService 값을 설정하거나 변경할 방법이 없어서 결국 setter를 만들어야 한다.
순수 java 코드로 사용할 수 없다.(테스트 코드 작성이 어려움)
Application의 실행과 관계 없는 테스트 코드나 Spring에서만 사용하는 @Configuration 같은 곳에서 주입할 때 주로 사용한다.
4. 일반 메서드 주입
@Component
public class MyApp {
private MyService myService;
// 일반 메서드 주입
@Autowired
public void init(MyService myService) {
this.myService = myService;
}
public void run() {
myService.doSomething();
}
}
생성자, setter 주입으로 대체가 가능하여 사용하지 않는다.
생성자 주입을 선택하는 이유
불변(immutable)
- 어떤 Web Application을 만들지 정했다면 이미 Bean과 의존 관계가 결정된다.
- 객체를 생성할 때 최초 한번만 호출된다.
- setter 주입을 사용하면 접근제어자가 public으로 설정되어 누구나 수정할 수 있게 된다.
실수 방지
- 순수 Java 코드로 사용할 때(테스트코드) 생성자의 필드를 필수로 입력하도록 만들어준다.(NullPointerException 방지)
- 컴파일 시점에 오류를 발생 시킨다. 즉 실행 전에 오류를 알 수 있다.
- Spring Framwork에 의존하지 않아도 객체 지향 특성을 가장 잘 사용하는 방법이다.
// 생성자 주입 방식
@Component
public class MyApp {
// 필드에 final 키워드 필수! 무조건 값이 있도록 만들어준다.(필수)
private final MyService myService;
// 생성자를 통해 의존성 주입, 생략 가능
@Autowired
public MyApp(MyService myService) {
this.myService = myService;
}
public void run() {
myService.doSomething();
}
}
public class Main {
public static void main(String[] args) {
// MyService가 매개변수로 꼭 들어가야 한다.
MyApp myApp = new MyApp();
myApp.run();
}
}
@RequiredArgsConstructor
실제 웹 애플리케이션을 개발하면 대부분이 불변 객체이고 생성자 주입 방식을 선택하게 된다. 이런 반복되는 코드를 편안하게 작성하기 위해 롬복에서 제공하는 어노테이션이다.
- final 필드를 모아서 생성자를 자동으로 만들어 준다
- Annotaion Processor가 동작하며 컴파일 시점에 자동으로 생성자 코드를 만들어준다.
- 사용 방법
@Component @RequiredArgsConstructor public class MyApp { // 필드에 final 키워드 필수! 무조건 값이 있도록 만들어준다.(필수) private final MyService myService; // Annotation Processor가 만들어 주는 코드 // public MyApp(MyService myService) { // this.myService = myService; // } public void run() { myService.doSomething(); } } - 만약 생성자가 필요한 경우가 생기면, 생성자 주입 방식을 직접 선언하면 된다.
생성자를 하나 만들고 @Autowired를 사용한 코드와 똑같이 동작한다.
'spring' 카테고리의 다른 글
| Bean 등록 수동 VS 자동 (0) | 2025.02.04 |
|---|---|
| 같은 타입의 Bean 충돌 해결(@Qualifier @Primary) (0) | 2025.02.04 |
| 수동등록 bean(@Configuration, @Bean)과 자동등록 bean(@ComponentScan, @Component)이 충돌할 경우 (0) | 2025.02.04 |
| MVC와 템플릿 엔진, API (0) | 2025.01.31 |
| View 환경설정 (3) | 2025.01.31 |