spring공부함에 있어서 내용은 인프런 김영한님 강의를 듣고 정리한 것입니다 (필기 및 공부정리용)
자동 의존관계 설정
자동 의존관계 사용이유
관리해야 할 객체들이 한 두개 정도면 직접 의존관계를 설정을 해주어도 상관이 없겠지만 프로젝트가 커지고 관리해야할 것들이 많아진다면 직접 관리를 하는데 있어서는 어려움이 있을 것이다.
이를 돕기위해 spring은 Autowired라는 어노테이션을 이용해 의존관계 설정을 자동으로 도와준다
의존관계 설정하기 전
설정 파일에 자동 의존관계 설정을 명시
자바코드기반 설정 방법
@ComponentScan
을 사용
@Configuration
@ComponentScan(
excludeFilters = @ComponentScan.Filter(type=FilterType.ANNOTATION, value = Configuration.class)
)
public class AutoAppConfig {
}
참고:
@Configuration
를 들어가보면 해당 어노테이션에도@Component
가 있는 것을 확일 할 수 있다. 해서@Configuration
을 사용한 파일까지 spring bean으로 등록이 되기때문에 제외를 한 것이다.
*type 속성 값에 올수 있는 것 - ANNOTATION, ASSIGNABLE_TYPE, REGEX, ASPECTJ
- 컴포넌트 스캔의 기본 대상
- @Component
- @Controller - 스프링 MVC컨트롤러로 인식
- @Service - 부가적인 처리 없음 단순 계층인식 도움
- @Repository - 데이터 접근 계층으로 인식
- @Configuration - 스프링 설정정보 인식, 싱글톤 유지
xml기반 설정 방법
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--추가-->
<context:annotation-config/>
<bean id="memberService" class="com.jhs.Member.MemberServiceImpl">
<!--의존성 주입을 할 필요가 없음-->
</bean>
<bean id="orderService" class="com.jhs.Order.OrderServiceImpl">
<!--의존성 주입을 할 필요가 없음-->
</bean>
<bean id="memberRepository" class="com.jhs.Member.MemoryMemberRepository"/>
<bean id="discountPolicy" class="com.jhs.Discount.FixDiscountPolicy"/>
</beans>
컴포넌트 스캔
@ComponentScan
- 프로젝트내에서
@Component
가 붙은 모든 프로젝트를 스캔을 해서 spring bean으로 등록을 해준다 - spring bean의 기본 이름은 클래스명의 앞글자를 소문자로 바꿔서 사용한다
- `@Component("name") bean이름을 직접 지정하여 사용할 수 있다
- 스캔 시작 위치를 지정할수 있다
- java 설정방법
@ComponentScan(basePackages="시작위치")
- xml 설정방법
<context:component-scan base-package="시작위치">
- java 설정방법
@Autowired
@Component //해당 어노테이션을 추가를 해준다
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired //해당 어노테이션을 추가를 해준다
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member member = memberRepository.findById(memberId);
int discountPrice = discountPolicy.discount(member, itemPrice);
return new Order(memberId, itemName, itemPrice, discountPrice);
}
}
- 컴포넌드 스캔을 통해서 등록된 spring bean을 조회하여 의존성을 주입을 해준다
- 생성자가 하나만 있다면
@Autowired
를 생략을 해도 된다
자동주입을 설정을 했는데 해당 bean이 없다면 에러가 생긴다
이때 단순히 null값으로 유지를 하기를 원한다면 @Autowired(required=false)
로 설정하여 존재하지 않아도 에러가 발생하지 않는다
주로 생성자로 의존성을 주입하는 것이 아닌 setter를 사용하여 주입을 하는경우 사용이 될듯 하다 개발자가 모르고 set을 하지 않았을 경우 혹은 하지 않아도 되는 경우와 같을때 사용이 될 것 같다
참고 의존성을 주입하는 방법에는 이외에도 필드를 통한 주입, 일반 메서드를 통한 주입 방법이 있지만 필드를 통한 주입은 외부에서 변경이 불가능 하고 di가 없으면 사용이 불가능하다
찾아보니 주로 생성자와 setter를 통한 주입 방식이 많이 사용되는 듯 하다
또한 생성자를 통한 주입을 할 시에는
final
키워드를 통해서 필히 주입을 받게끔 만들고 주입이 되지 않는다면 컴파일 오류가 나서 찾기 쉽다
@Autowired(required = false)
public void setMemberRepository(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
중복 빈 등록
@Component
public class FixDiscountPolicy implements DiscountPolicy {
private final int discountFixAmount = 1000;
@Override
public int discount(Member member, int price) {
if(member.getGrade() == Grade.VIP)
return discountFixAmount;
else
return 0;
}
}
@Component
public class RateDiscountPolicy implements DiscountPolicy {
private final int discountRate = 10;
@Override
public int discount(Member member, int price) {
if(member.getGrade() == Grade.VIP)
return price * discountRate / 100;
else
return 0;
}
}
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
orderservice는 discountPolicy라는 객체를 의존을 받아야 하는데 동일한 타입의 bean이 두개가 등록이 된다면 에러가 발생하게 된다
이를 방지하기 위해서 @Qualifier
, @Primary
를 사용을 하면 된다 spring bean을 특정시킨다고 생각을 하면 될 것 같다
설정방법
- xml 기반설정
<context:annotation-config/>
<bean id="memberService" class="com.jhs.Member.MemberServiceImpl">
</bean>
<bean id="orderService" class="com.jhs.Order.OrderServiceImpl">
</bean>
<bean id="memberRepository" class="com.jhs.Member.MemoryMemberRepository"/>
<bean id="fixdiscountPolicy" class="com.jhs.Discount.FixDiscountPolicy"/>
<bean id="ratediscountPolicy" class="com.jhs.Discount.RateDiscountPolicy">
<qualifier value="primary"/> <!--추가-->
</bean>
- java 기반설정
@Component
@Qualifier("primary")//추가
public class RateDiscountPolicy implements DiscountPolicy {
private final int discountRate = 10;
@Override
public int discount(Member member, int price) {
if(member.getGrade() == Grade.VIP)
return price * discountRate / 100;
else
return 0;
}
}
- 사용방법
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
@Qualifier("primary")/*추가*/ DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
위 예시에서 Qualifier
의 이름을 primary로 지정을 하였는데 Qualifier
을 사용하는 것이 아닌 @Primary
를 사용하여 우선순위를 줄 수도 있다
@Component
@primary //추가
public class RateDiscountPolicy implements DiscountPolicy {
private final int discountRate = 10;
@Override
public int discount(Member member, int price) {
if(member.getGrade() == Grade.VIP)
return price * discountRate / 100;
else
return 0;
}
}
@Qualifier
와 @Primary
를 둘다 사용 할 경우에는 @Qualifier
가 우선순위가 더 높게 설정 된다
spring공부함에 있어서 내용은 인프런 김영한님 강의를 듣고 정리한 것입니다 (필기 및 공부정리용)
'공부기록 > Spring' 카테고리의 다른 글
Spring MVC1 (0) | 2021.12.31 |
---|---|
Spring MVC 세팅 (0) | 2021.12.31 |
Spring - Bean (0) | 2021.12.24 |
Spring - DI (0) | 2021.12.06 |
Spring 다시시작 (0) | 2021.12.04 |