Bean으로 등록하기 위한 스프링의 애너테이션

1. @Component : 객체(컴포넌트)를 나타내는 일반적인 타입으로 태그와 동일한 역할

2. @Repository : 퍼시스턴스(persistence) 레이어, 영속성을 가지는 속성(파일, 데이터베이스)를 가진 클래스

--EX) DAO

3. @Service : 서비스 레이어, 비즈니스 로직을 가진 클래스

--EX) Service

4. @Controller: 프리젠테이션 레이어, 웹 애플리케이션에서 View에서 전달된 웹 요청과 응답을 처리하는 클래스

(2,3,4 는 1의 구체화 형태인 셈)

 

 DI 주입을 위한 스프링의 애너테이션

1. @Autowired : property, constructor-arg 태그와 동일한 역할을 한다 ,

 의존하는 객체를 주입할 때 주로 Type을 이용하게 된다.

2. @Resource : 애플리케이션에서 필요로 하는 자원을 자동 연결할 때 사용된다.

3. @Value: 단순한 값을 주입할 때 사용되는 어노테이션이다.

 

<context:component-scan> 태그

@Component를 통해 자동으로 Bean을 등록하고, @Autowired로 의존 관계를 주입받는 어노테이션을 클래스에서 선언하여 사용했을 경우에는 해당 클래스가 위치한 특정 패키지를 Scan 하기 위한 설정을 XML에 해주어야한다. 이 때 사용하는 태그이다

스프링 컨테이너: BeanFactory를 기반으로 Bean 클래스들을 제어할 수 있는 기능을 지원한다.

 

스프링의 동작 구조 : 

Request -> Servlet 컨테이너 -> Spring 컨테이너(new XmlWebApplicationContext()-> servlet-context.xml불러옴 )

*servlet-context.xml : spring 컨테이너가 실행해야 하는 내용을 설정하는 파일

(트랜잭션 관리, DI, AOP 등 관리)

 

즉, 

1. 요청

2. 서블릿 컨테이너 - DispatcherServlet이 받음 (Web.xml 포함됨)

3. HandlerMapping ( 해당 요청을 매핑한 컨트롤러가 있는지 검색 -- @RequestMapping() 제공)

4. 처리 요청 +Bean등록

5. 결과를 출력할 View 리턴

6. DispatcherServlet에서 ViewResolver를 통해 view 검색 처리

 

[읽어들이는 순서]

-서버 구동시 web.xml 제일먼저 읽음

-그 안의 context-param 가장 먼저 읽음

-그 안에 root-context(자원관련 , DB ) / spring-security xml을 써놨고 제일 먼저 작동됨

-bean (스프링에서 생성하고 관리하는 객체) 으로 정의해놓음

-클라이언트가 요청시 dispatcher servlet 읽음 == 서블릿 컨테이너가 먼저 받음 ==> 스프링 컨테이너로 넘겨줌

-스프링 컨테이너의 servlet-context.xml의 설정대로 요청 받게됨 -> Handler Mapping -> 
     요청받은 주소를 처리할 클래스나 메서드에 지정하는 역할 (어노테이션 형식 사용) ==> @Controller, @RequestMapping 이 쓰임

-component-scan이 작동됨 -> 처리진행 -> 문자열 반환

-반환받은 문자열에 앞뒤 경로 붙여서 View Resolver 에서 응답 경로 내보냄

 

Bean? 

-스프링이 IoC 방식으로 관리하는 객체 / 스프링이 직접 생성과 제어를 담당

 

<스프링 컨테이너와 스프링 빈> 작동 단계
1. 스프링컨테이너 생성
2. 스프링 빈 등록
3. 스프링 빈 의존관계 설정 준비
4. 스프링 빈 의존간계 설정 완료

 

<스프링 빈 조회 - 상속관계>
-> 부모타입으로 조회하면 자식타입도 모두 조회됨

 

<IoC컨테이너>

Bean 생성 객체 : BeanFactory  <- ApplicationContext  <- AnnotaionConfig ApllicationContext (상속)

BeanFactory  :스프링 컨테이너 최상위 인터페이스 / 스프링의 IoC 담당하는 핵심

ApplicationContext  : 팩토리 상속받아 빈 관리 + 부가기능위해 (실질적 사용)

 

* 스프링 컨테이너는 다양한 형식의 설정 정보를 받아들일수 있게 설계됨

(애너테이션, XML)

HOW? BeanDefinition이라는 추상화 덕분에 여기서 메타정보만 가져오면 스프링 빈을 생성할 수 있다.

 

<싱글톤 패턴>
대부분의 스프링 애플리케이션은 웹 -> 여러 고객이 동시에 요청을 한다
==> 문제점 : 요청시마다 계속 객체 생성해줘야함 ==>메모리 낭비가 극심
--> 1개의 객체를 공유하도록 설계 == 싱글톤 패턴

 

싱글톤 패턴 : 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴
--> 2개 이상 생성을 막는다 == private으로 외부 new 막는다
==>스프링에선 자동으로 싱글톤 지원해줌

 

문제 : 
1. 코드가 길어짐
2. 구체클래스에 의존한다 DIP 위반
3. == OCP 위반
4. 테스트 어려움
5. 유연성 떨어짐, 자식클래스 만들기 어려움

==> 스프링에서는 싱글톤 패턴 문제-> 싱글톤 컨테이너에서 해결함
싱글톤 컨테이너 : 싱글턴 패턴 적용 없이 싱글톤으로 관리
-> 스프링 컨테이너에서 관리.
-> 이미만들어진 객체를 공유해서 재사용

 

<싱글톤 방식의 주의점!!>
-> 상태를 유지하게 설계하면 안된다
== 만약 유저1일 100의 값을 넣은 상태에서 유저 2가 200의 값을 넣고 유저1이 값을 조회한다면?
==> 문제발생

 

<@Configuration> : 스프링의 싱글톤을 위해 존재한다
만약 두개의 bean에서 동일한 객체를 new로 생성한다면?각각 new 해야 맞지만 스프링이 싱글톤을 관리해줌 ==모두 같은 인스턴스가 공유되어 사용됨
HOW? 
bean을 출력해보면 클래스 경로 + CGLIB를 붙혀버림 (상속 클래스를 하나 더 추가해서 조작함) => 이것이 유지해줌
1. 이미 스프링컨테이너에서 있으면? 스프링 컨테이너에서 반환
2. 아니면? 기존 로직을 호출해서 스프링 컨테이너에 등록하고 반환

-> @Configuration이 해주는 일이므로 @bean만 쓰면 싱글톤이 유지되지 않는다!

스프링의 핵심 가치 = 객체지향 프로그래밍이다

그런다면 좋은 객체지향 프로그래밍이란?
--객체를 설계할 떄 역할과 구현을 명확히 분리해야 함--

==  구현을 뭐로 바꾸든 역할은 변함없어야한다 ==
1) SRP : 단일책임원칙
-한 클래스는 하나의 책임만 가져야한다
2) OCP : 개방-폐쇄 원칙 
- 소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀있어야 한다 (다형성 의미)
3) LSP 리스코프 치환 원칙 : 

-프로그램의 객체는 정확성을 깨지 않으면서 하위 타입 인스턴스로 바꿀 수 있어야한다
4) ISP 인터페이스 분리 원칙 : 

-인터페이스 여러개가 범용 한개보다 낫다
5) DIP 의존관계 역전 원칙 : 

-추상화에 의존해야지 구체화에 의존하면 안된다 ( 인터페이스에 의존해라)

 

이를 위해 다형성이 중요하다! 하지만 다형성 만으로는 쉽게 갈아끼우듯 사용이 어려움 -> 스프링의 탄생

 

EX) 인터페이스1 = new 구현체 1

이라는 구문에서 구현체 1이 구현체 2로 바뀐다면?

---->정의하는 new 코드를 바꿔주어야한다

 

결국 해당 클래스는 인터페이스를 사용하며 DIP를 준수해서 추상화에 의존한것처럼 보였지만 

사실 인터페이스와 구현체 둘 전부에 의존해있는 상태인 것이다

-> 이러한 문제를 해결하기 위해 생성자 안에 무엇을 전달받던 그냥 받기만 하는 상태로 만들어

자신의 역할에만 집중할 수 있도록 해주고

누군가가 생성의 역할을 해줘야 좋은 설계이다. 그리고 이것이 스프링의 원리가 된다!

 

 

[  스프링 프레임워크란?  ]

자바 플랫폼을 위한 오픈 소스 애플리케이션 프레임워크로 간단하게 스프링이라고도 불린다

동적인 웹 사이트를 개발하기 위한 여러가지 서비스를 제공

 

[  Spring Framework의 특징 ]

1. IOC ( Inversion of Control) : 제어 반전

-> 컨트롤의 제어권이 개발자가 아니라 프레임워크에 있다는 뜻으로 객체의 생성부터

모든 생명주기의 관리까지 프레임워크가 주도하고 있다. 객체를 생성하고 직접 호출하는 프로그램이 아니라, 만들어둔 자원을 호출해서 사용한다

 

2. DI ( Dependency Injection) : 의존성 주입

-> 설정 파일이나 어노테이션을 통해 객체간의 의존 관계를 설정하여 개발자가 직접 객체를 생성할 필요가없다.

 

3. POJO (Plain Old java Object)기반 프레임워크 : 

-> J2EE, EJB 와 같은 특정 기술이나 라이브러리의 내용을 상속받아 클래스를 구현하지 않고 일반적인 기본 기능만을 가진 순수한 자바 객체를 의미한다. 특정 클래스에 종속되지 않으므로 자바의 객체지향적 설계가 쉬워지고,

코드길이 감소, 유지보수성 증가, 기존 Java API, 라이브러리 지원에 용이하다.

 

4. Spring AOP (Aspect Oriented Programming) : 관점 지향 프로그래밍

-> 트랜잭션, 로깅, 보안 등 여러 모듈, 여러 계층에서 공통으로 필요로하는 기능의 경우 해당 기능들을 분리하여 관리

 

5. Spring JDBC -> Mybatis나 Hibermate 등의 데이터베이스를 처리하는 영속성 프레임워크와 연결 인터페이스 제공

 

6. Spring MVC -> MVC 디자인 패턴을 통해 웹 어플 M V C 사이의 의존 관계를 DI 컨테이너에서 관리하여 개발자가 아닌 서버가 객체들을 관리하는 웹 어플을 구축할 수 있다.

 

7. PSA -> 스프링은 여러 모듈을 사용함에 있어 별도의 추상화 레이어를 제공한다.

 

[  Spring MVC 요청 처리 과정  ] 

1. Client 웹 브라우저에서 Request 보냄 

2. 서블릿 컨테이너 Dispatcher Servlet <-> Handler Mapping 스프링 컨테이너

3. Mapping되는 Controller -> 로직 실행 ->View Resolver

4. 반환할 view 리턴 -> Response 

 

 

 

 

 

 

 

 

 

+ Recent posts