
[Spring] 객체 지향 설계와 스프링
[Spring] 좋은 객체 지향 설계의 5가지 원칙(SOLID)
[Spring] 객체 지향 원리 적용
[Spring] IoC, DI위 글에서 작성한 코드들은 스프링을 사용한 코드가 아닌 순수 자바 코드만으로 작성된 것이다.
이제 이 코드에 스프링을 적용해볼 것이다.
AppConfig에 설정을 구성한다는 뜻의
@Configuration을 붙여준다.
각 메서드에@Bean을 붙여준다. 이렇게 하면 스프링 컨테이너에 스프링 빈으로 등록한다.이때 key, value 형태로 저장된다.
@Bean(name = "newname")과 같이 따로 이름을 설정하지 않으면
메서드의 명을 스프링 빈의 key로 사용한다.
주의이름은 반드시 유일해야한다.
같게 된다면 다른 빈이 무시되거나, 기존 빈을 덮어버리는 등 오류가 발생한다.import hello.core.member.MemberRepository; import hello.core.member.MemberService; import hello.core.member.MemberServiceImpl; import hello.core.member.MemoryMemberRepository; import hello.core.order.OrderService; import hello.core.order.OrderServiceImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AppConfig { @Bean public MemberService memberService() { return new MemberServiceImpl(memberRepository()); } @Bean public OrderService orderService() { return new OrderServiceImpl( memberRepository(), discountPolicy()); } @Bean public MemberRepository memberRepository() { return new MemoryMemberRepository(); } @Bean public DiscountPolicy discountPolicy() { return new RateDiscountPolicy(); } }
이전 코드는 필요한 객체를
AppConfig를 사용해서 직접 조회했지만,
이제부터는 스프링 컨테이너를 통 해서 필요한 스프링 빈(객체)를 찾아야 한다.스프링 빈은
applicationContext.getBean()메서드를 사용해서 찾을 수 있다.package hello.core; import hello.core.member.Grade; import hello.core.member.Member; import hello.core.member.MemberService; import org.springframework.context.ApplicationContext; importorg.springframework.context.annotation.AnnotationConfigApplicationContext; public class MemberApp { public static void main(String[] args) { // 수정 전 // AppConfig appConfig = new AppConfig(); // MemberService memberService = appConfig.memberService(); // 수정 후 ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); MemberService memberService = applicationContext.getBean("memberService", MemberService.class); Member member = new Member(1L, "memberA", Grade.VIP); memberService.join(member); Member findMember = memberService.findMember(1L); System.out.println("new member = " + member.getName()); System.out.println("find Member = " + findMember.getName()); } }
MemberApp과 동일하다.이전 코드는 필요한 객체를
AppConfig를 사용해서 직접 조회했지만,
이제부터는 스프링 컨테이너를 통 해서 필요한 스프링 빈(객체)를 찾아야 한다.스프링 빈은
applicationContext.getBean()메서드를 사용해서 찾을 수 있다.package hello.core; import hello.core.member.Grade; import hello.core.member.Member; import hello.core.member.MemberService; import hello.core.order.Order; import hello.core.order.OrderService; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class OrderApp { public static void main(String[] args) { // 수정 전 // AppConfig appConfig = new AppConfig(); // MemberService memberService = appConfig.memberService(); // OrderService orderService = appConfig.orderService();\ // 수정 후 ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); MemberService memberService = applicationContext.getBean("memberService", MemberService.class); OrderService orderService = applicationContext.getBean("orderService", OrderService.class); long memberId = 1L; Member member = new Member(memberId, "memberA", Grade.VIP); memberService.join(member); Order order = orderService.createOrder(memberId, "itemA", 10000); System.out.println("order = " + order); } }
ApplicationContext를 스프링 컨테이너라 한다.기존에는 개발자가
AppConfig를 사용해서 직접 객체를 생성하고 DI를 했지만,
이제부터는 스프링 컨테이너를 통해서 사용한다.스프링 컨테이너는
@Configuration이 붙은AppConfig를 설정(구성) 정보로 사용한다.
여기서
@Bean이 라 적힌 메서드를 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록한다.
이렇게 스프링 컨테이너에 등록된 객체를 스프링 빈이라 한다.
스프링 빈은@Bean이 붙은 메서드의 명을 스프링 빈의 이름으로 사용한다.
(memberService,orderService)
기존에는 개발자가 직접 자바코드로 모든 것을 했다면
이제부터는 스프링 컨테이너에 객체를 스프링 빈으로 등록하고,
스프링 컨테이너에서 스프링 빈을 찾아서 사용하도록 변경되었다.
코드가 약간 더 복잡해진 것 같은데, 스프링 컨테이너를 사용하면 어떤 장점이 있을까?
개발자가 직접 객체를 생성하고 관리할 필요가 없습니다.
스프링 컨테이너가 대신하여 객체의 생명주기를 관리합니다.
이로 인해 코드는 더 깔끔하고 유지보수가 쉬워집니다.
스프링 컨테이너는 빈(Bean) 간의 의존성을 자동으로 주입해줍니다.
이로 인해 각 클래스는 자신의 의존성에 대해 알 필요가 없게 되며,
유연하고 확장성 있는 코드를 작성할 수 있습니다.
스프링 컨테이너는 기본적으로 빈을 단일체로 관리합니다.
따라서 애플리케이션 전체에서 해당 빈의 인스턴스는 하나만 존재하게 됩니다.
스프링은 AOP를 내장하여 교차 관심사(cross-cutting concerns)를 분리하여 코드 중복을 줄이고,
핵심 비즈니스 로직에만 집중할 수 있게 도와줍니다.
스프링은 선언적 트랜잭션 관리를 지원하여,
복잡한 트랜잭션 관리 로직 없이도 데이터의 일관성과 안정성을 유지할 수 있습니다.
스프링 프레임워크는 웹 MVC, 보안, 데이터 엑세스, 메시징 등 다양한 모듈을 제공합니다.
이러한 모듈들은 잘 통합되어 있어 개발자는 필요한 기능을 효과적으로 사용할 수 있습니다.
스프링의 의존성 주입 기능을 활용하면, 유닛 테스트와 통합 테스트를 쉽게 작성하고 실행할 수 있습니다.
스프링은 경량 프레임워크이므로, 애플리케이션의 부하를 최소화하면서 필요한 기능만을 사용할 수 있습니다.
스프링은 크고 활발한 커뮤니티와 광범위한 문서화를 통해 지원받을 수 있습니다.
이로 인해 문제 해결이나 새로운 기능에 대한 학습이 더욱 쉬워집니다.