스프링은 설정 정보 없이 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능을 제공한다.
// MemberService.java
@Component
public class MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
public void createMember(Member member) {
memberRepository.postMember(member);
}
public Member getMember(Long memberId) {
return memberRepository.getMember(memberId);
}
public void deleteMember(Long memberId) {
memberRepository.deleteMember(memberId);
}
}
// CoffeeService.java
@Component
public class CoffeeService {
private static CoffeeRepository coffeeRepository;
@Autowired
public CoffeeService(CoffeeRepository coffeeRepository) {
this.coffeeRepository = coffeeRepository;
}
public void createCoffee(Coffee coffee) {
coffeeRepository.postCoffee(coffee);
}
public Coffee editCoffee(Long coffeeId, String korName, int price) {
return coffeeRepository.patchCoffee(coffeeId, korName, price);
}
public Coffee getCoffee(Long coffeeId) {
return coffeeRepository.getCoffee(coffeeId);
}
public void deleteCoffee(Long coffeeId) {
coffeeRepository.deleteCoffee(coffeeId);
}
}
// MemberRepository.java
@Component
public class MemberRepository {
private static Map<Long, Member> members = new HashMap<>();
public void postMember(Member member) {
members.put(member.getMemberId(), member);
}
public Member getMember(Long memberId) {
return members.get(memberId);
}
public void deleteMember(Long memberId) {
members.remove(memberId);
}
}
// CoffeeRepository.java
@Component
public class CoffeeRepository {
private static Map<Long, Coffee> drinks = new HashMap<>();
public void postCoffee(Coffee coffee) {
drinks.put(coffee.getCoffeeId(), coffee);
}
public Coffee patchCoffee(Long coffeeId, String korName, int price) {
Coffee drink = drinks.get(coffeeId);
drink.setKorName(korName);
drink.setPrice(price);
return drinks.put(coffeeId, drink);
}
public Coffee getCoffee(Long coffeeId) {
return drinks.get(coffeeId);
}
public void deleteCoffee(Long coffeeId) {
drinks.remove(coffeeId);
}
}
탐색할 패키지의 시작 위치를 지정하고, 해당 패키지부터 하위 패키지까지 모두 탐색한다.
필터
스프링에서 DI할 수 있는 의존 관계 주입에는 네 가지 방법이 있다.
생성자는 통하여 의존 관계를 주입 받는 방법이다.
생성자에 @Autowired를 하면 스프링 컨테이너에 @Component로 등록된 빈에서 생성자에 필요한 빈들을 주입한다.
@Component
public class CoffeeService {
private final MemberRepository memberRepository;
private final CoffeeRepository coffeeRepository;
@Autowired
public CoffeeService(MemberRepository memberRepository, CoffeeRepository coffeeRepository) {
this.memberRepository = memberRepository;
this.coffeeRepository = coffeeRepository;
}
}
setter라 불리는, 필드의 값을 변경하는 수정자 메서드를 통해서 의존 관계를 주입하는 방법이다.
특징
예제
@Component
public class CoffeeService {
private MemberRepository memberRepository;
private CoffeeRepository coffeeRepository;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Autowired
public void setCoffeeRepository(CoffeeRepository coffeeRepository) {
this.coffeeRepository = coffeeRepository;
}
}
필드에 @Autowired를 붙여서 바로 주입하는 방법이다.
@Component
public class CoffeeService {
@Autowired
private MemberRepository memberRepository;
@Autowired
private CoffeeRepository coffeeRepository;
}
일반 메서드를 사용해 주입하는 방법이다.
주입할 스프링 빈이 없을 때 동작해야하는 경우가 있다.
@Autowired만 사용하는 경우 required 옵션 기본값인 true가 사용되어 자동 주입 대상이 없으면 오류가 발생하는 경우가 있을 수 있다.
스프링 빈을 옵셔널하게 해둔 상태에서 등록이 되지 않고, 기본 로직으로 동작하게 하는 경우
자동 주입 대상 옵션 처리 방법
예제
public class AutowiredTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class);
}
static class TestBean {
@Autowired(required = false)
public void setNoBean1(Member noBean1) {
System.out.println("noBean1 = " + noBean1);
}
@Autowired
public void setNoBean2(@Nullable Member noBean2) {
System.out.println("noBean2 = " + noBean2);
}
@Autowired
public void setNoBean3(Optional<Member> noBean3) {
System.out.println("noBean3 = " + noBean3);
}
}
}
// 출력 결과
noBean2 = null
noBean3 = Optional.empty
과거에는 수정자, 필드 주입을 많이 사용했지만, 최근에는 대부분 생성자 주입 사용을 권장한다.