일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 옵저버 패턴
- 자바의 면접
- 스프링 빈
- try-catch
- @Tranctional
- 참조형 반환타입
- Class Loader
- 싱글톤 패턴
- 팩토리 패턴
- 스프링 싱글톤
- TCP/IP 4계층
- 팩토리패턴
- 백준 1935
- 스프링 컨테이너
- removeAll
- 백준 2164
- www.naver.com치면 발생하는일
- 리버스 프록시
- 포워드 프록시
- 전략 패턴
- 네트워크
- 빈 타입 조회
- mvvm패턴
- 참조형 매개변수
- k번째큰수
- 쇠막대기
- 기본형 매개변수
- 후위표기식
- 스프링
- SOLID원칙
- Today
- Total
스파이더 웹 개발
Spring의 전반적인 공부 ch01 본문
스프링의 핵심 기능은 객체를 생성하고 초기화 하는 것이다
별도의 설정이 없는경우 스프링은 한개의 빈 객체만을 생성하며 이때 빈 객체는 '싱글톤 범위를 갖는다' 고 표현한다
스프링은 기본적으로 한개의 @Bean 어노테이션에 대해 한 개의 빈 객체를 생성한다
그러므로 아래 코드는 다른 각각의 객체를 생성한다
@Bean
public Test test1() {
Test t = new Test();
return t;
}
@Bean
public Test test2() {
Test t = new Test();
return t;
}
DI
DI는 의존주입을 의미하며, 의존이란 객체 간의 의존을 의미한다. 자세히 풀어서 설명하면 한 클래스가 다른 클래스의 메서드를 실행할 때 이를 이를 '의존' 한다고 표현한다
아래 간단한 예제를 통해 살펴보자
public class MemberService {
private MemberDao memberDao = new MemberDao();
public void regist(RegisterRequest req) {
Member member = memberDao.selectByEmail(req.getEmail());
if (member != null) {
throw new DuplicateMemberException("dup email " + req.getEmail());
}
Member newMember = new Member(
req.getEmail(), req.getPassword(), req.getName(),
LocalDateTime.now());
memberDao.insert(newMember);
return newMember.getId();
}
}
해당 예제는 DB와 연결되어있는 DAO 객체를 Service 클래스에서 생성하여, 회원가입시 해당 이메일 존재하면 예외를 발생시키고 그렇지않으면 회원가입하는 예제이다. 방금 말한 의존이란, Service 클래스에서 Dao의 메서드인 selectByEmail or insert 메서드를 실행하는것을 의미한다고 볼 수 있다.
또한 의존은 변경에 의해 영향을 받게 되는데, MemberDao 클래스에서 selectByEmail의 메서드를 -> findEmail 로 변경하면 Service 클래스에서 또한 코드를 변경해주어야 한다.
의존하는 대상을 구하는 방법은 위의 코드처럼 객체를 직접 생성하는 것도 있지만 매우 지양해야 할 방법이다
그렇다면? 어느 방법이 객체지향스러우며 유지보수에 유용할까!
그건 DI 즉, 현재 배우려고한느 의존성 주입을 통한 의존처리를 해주면된다
위의 코드를 아래코드처럼 변경해주면된다
public class MemberRegisterService {
private MemberDao memberDao;
public MemberRegisterService(MemberDao memberDao) {
this.memberDao = memberDao;
}
.... 그이외 코드는 동일
}
즉, 객체를 직접 생성하는 것이 아닌 외부에서 객체를 주입 받는 것이다
주입을 받는것이 어떠한 장점이 있을까라는 생각이 들 수 있는데, 객체간의 의존성을 낮추고 유연성을 높일 수 있다
예를 들어 여러 클래스에서 MemberDao를 의존하고 있으며, MemberDao를 상속한 클래스를 의존해야한다고 가정하면, 객체를 직접 생성하는 경우에는 지금처럼 모든 클래스의 코드를 변경을 해줘야한다.
class ChildDao extends MemberDao {
}
public class MemberService {
// private MemberDao memberDao = new MemberDao();
private MemberDao memberDao = new ChildDao();
}
public class ChildService {
// private MemberDao memberDao = new MemberDao();
private MemberDao memberDao = new ChildDao();
}
그러나 의존주입을 받는 경우 의존하고있는 클래스들에서는 코드를 변경할 필요가 없고 단순히 외부에서 주입할 클래스에서만 바꿔주면 의존하고있는 클래스들에 모두 적용되기에 유지보수의 편리성이 증대된다
class ChildDao extends MemberDao {
}
public class MemberService {
private MemberDao memberDao;
MemberService(MemberDao memberDao){
this.memberDao=memberDao;
}
}
public class ChildService {
private MemberDao memberDao;
ChildService(MemberDao memberDao){
this.memberDao=memberDao;
}
}
그렇다면 여기서 의아한점은 객체를 직접 생성하는 것보단 외부에서 주입받는 것의 장점은 알겠다는 건데, 그렇다면 어디서 넣어주냐 이거다. 그것은 따로 설정 클래스를 생성하고 해당 클래스에서 의존성 주입에 대한 코드를 작성 해주면된다
스프링에서는 아래 예시처럼 외부 설정클래스를 만들고 의존을 어떻게 주입할 지 정의한 설정 정보를 작성하면 된다
@Configuration
public class AppCtx {
@Bean
public MemberDao memberDao() {
return new MemberDao();
}
@Bean
public MemberService memberService() {
return new MemberService(memberDao());
}
}
@Configuration 어노테이션은 스프링 설정 클래스를 의미한다
@Bean 어노테이션은 해당 타입을 반환하는 객체를 스프링 빈으로 등록하는 것을 의미한다
지금까지 의존성 주입에 대해 알아보았는데, 예제에서는 전부 생성자 주입을 사용하였다. 의존성 주입 방식에는 생성자 방식이외에도 다른 방식이있는데,확인해보자
다른 방법으로는 세터 메서드 방식으로도 객체를 주입받을 수 있다
아래 예제를 살펴보자
public class MemberService {
private MemberDao memberDao;
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
}
@Configuration
public class AppCtx {
@Bean
public MemberDao memberDao() {
return new MemberDao();
}
@Bean
public MemberService memberService() {
MemberService servcie = new MemberService();
service.setMemberDao(memberDao());
return servcie;
}
}
코드를 보면 생성자 주입과 크게 차이가없는 것 같다 그러나, 스프링에서는 생성자 주입을 권장하는데, 그 이유는 순환참조를 방지하고, 불변객체를 만들 수 있어서 이다
여기서 추가적으로 개발자의 코드를 줄일려는 욕심은 끝이없는데, 설정클래스인 AppCtx클래스에서 set메서드를 호출하여, memberDao() 객체를 주입해준 것을 확인하였다. 내가 코드로 주입하는게아니라 자동주입이 있다면 어떨까? 아마 더편리할 것이다 그게 바로 @Autowired 어노테이션을 사용하는 것이다
위의 코드를 자동주입 @Autowired를 사용하면 변경한 코드이다
public class MemberService {
private MemberDao memberDao;
@Autowired
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
}
@Configuration
public class AppCtx {
@Bean
public MemberDao memberDao() {
return new MemberDao();
}
@Bean
public MemberService memberService() {
MemberService servcie = new MemberService();
return servcie;
}
}
set메서드 위의 @Autowired 어노테이션을 붙여줬는데, 동작원리는 스프링 컨테이너가 자동으로 해당 타입의 빈 객체를 찾아 주입해준다
'Spring' 카테고리의 다른 글
Spring의 전반적인 공부 ch03 (0) | 2022.09.03 |
---|---|
Spring의 전반적인 공부 ch02 (0) | 2022.08.25 |
HTTP 헤더 (0) | 2022.08.12 |
HTTP 상태 코드 (0) | 2022.08.12 |
HTTP 메서드 (0) | 2022.08.11 |