Spring

업데이트:

스프링컨테이너
  • 스프링은 스프링 컨테이너또는 애플리케이션 컨텍스트라고 불리는 스프링 런타임 엔진을 제공한다.
  • 스프링 컨테이너는 설정 정보를 참고해서 애플리케이션을 구성하는 오브젝트를 생성하고 관리한다.
loC(제어의 역행)
  • 메소드나 객체의 호출작업을 개발자가 결정하는 것 이 아닌 외부에서 결정하는 것을 의미(의존성 주입을 통한 관계의 역전)객체관의 의존관계를 개발자가 정해주는게 아닌 스프링 컨텍스트로 위임
DI(의존성 주입)
  • 제어의 역행이 일어날떄 스프링 내부에 있는 객체(빈이라고 함)들 간의 관계를 관리할때 의존적 객체를 직접 생성하거나 제어 하는게 아닌 주입을통해서 필요한 객체를 외부에서 결정하여 연결
Java를 통한방식 DI
  • @Component : 해당 애너테이션은 컴포넌트 클래스임을 나타내고, 클래스를 빈으로 만들어야 함을 스프링에 단서로 제공한다. 컴포넌트 스캐닝은 기본적으로 켜 있지는 않아 명시적으로 작성할 필요가 있다.
  • @ComponentScan : 설정 클래스로서 동일한 클래스를 기본 스캐닝 한다. 스프링은 그 패키지와 하위 패키지를 스캔하고 @Component로 애너테이트된 클래스를 찾아 자동으로 빈을 생성해 준다. 애트리뷰트 값과 사용할 애트리뷰트를 미러링 하는 하위 요소가 있다.
    • basePackages : 컴포넌트 스캔을 위한 베이스 패키지를 지정함으로써 다중 패키지 스캔이 가능하고 애플리케이션 코드와 분리하여 설정 코드를 패키지 안에서 보관할 수 있기 때문에 사용한다.
    • basePackageClasses : 패키지가 아닌 클래스를 스캔에 지정한다. 클래스가 어떤 패키지 안에 있든 컴포넌트 스캐닝을 위한 베이스 패키지로서 사용된다.
  • @Configuration : javaConfig 클래스 만들기의 핵심으로 설정 클래스로서 식별하고, 스프링 애플리케이션 컨텍스트에서 만들어진 빈의 자세한 내용이 포함 될 수 있다는 것을 나타낸다.
    • 스프링 설정용 코드로 어떠한 비즈니스 로직도 포함하지 않고, 비즈니스 로직이 있는 코드에 영향을 주지 않는다. 애플리케이션 로직 중 비즈니스 로직 외의 다른 부분과는 분리된 패키지이다.
  • @Bean : javaConfig에서 빈을 선언하기 위해서 사용하는 애너테이션으로 메소드와 동일한 ID를 받는다 name을 통해 다른이름을 사용할 수 있다. 해당 애너테이션이 붙어 있는 메소드들을 AnnotationCOnfigApplicationContext는 자동으로 실행하여 그 결과로 리턴하는 객체들을 기본적으로 싱글턴으로 관리를 하게 된다.
    • 메소드에 애너테이션을 통해 빈의 인스턴스가 등록된다. new Test() 객체를 린턴하는 메소드
    • 빈을 주입할때는 new Class(위에서 만들어진 메소드()) 리턴함 이미 만들어진 것을 리턴해주는 것을 보장(싱글톤)
    • @Component를 선언한 객체들만 가능한지는 확실히 확인필요 - , 하지 않아도 Bean을 통해 등록이 가능해 보이긴한다. Component Scan으로 사용하는 곳을 컨트롤러, 서비스, 맵퍼 등등으로 생각됨
  • @Import : 다른 javaConig 클래스를 가져올 수 있다. 다중 가능
  • @ImportResource : (classpath:{config xml name})을 통해 xml로 만들어진 config도 자바로 가져올 수 있다.
  • @ContextConfiguration : classes 를 통해 설정 클래스를 로드한다. @ComponentScan을 가지므로 설정된 빈들은 모두 사용 가능하다.
  • @Autowired : 빈을 테스트로 주입하는 클래스의 타입의 프로퍼티를 가진다.
    • 생성자, 프로퍼티 세터, 프로퍼티를 통해 오토와이어링이 된다.
    • 생성자나 세터 메소드를 포함한 어떤 메소드이든 스프링은 메소드 파라미터에 의존성을 가진다. 한 개의 빈이 일치하면 그 빈은 자동으로 와이어링 된다.
    • 매칭되는 빈이 없다면 스프링은 애플리케이션 컨텍스트가 생성될 떄 예외를 발생시킨다. 예외를 피하기 위해 required 애트리뷰트를 false로 설정한다.
    • @Inject를 대체로 사용가능
  • @Named : 빈에 이름을 부여하는 방식으로 사용
  • @ComponentScan와 @Configuration을 같이 사용해야 하는지 하나만 사용해야되는저 어떤게 더 유리한지에 대한 구분필요, 기본적인 인터페이스틀은 스캐닝으로 불러오고 나머지 비즈니스로직은 configuration을통해 관리??
XML을 통한 방식 DI
  • : base-package 를 지정해 컴포넌트 스캐닝을 활성화 한다.
  • : javaConfig의 @Bean과 유사한 XML로 패키지 경로를 포함한 완전한 클래스명으로 표현, id를 따로 지정할수 있다.
    • c:변수명-ref 통해 생성자 인자를 설정가능, _0(숫자)를 통해 변수명을 입력하지 않고 순서에 맞게 할수 있으며 하나일경우에는 _만 사용가능
    • ref를 제외하면 리터럴 값을 입력할 수 있음
    • p-네임스페이스를사용하면 프로퍼티를 와이어링 할 수 있다. p:{propertyname}-ref=”{beanId}”
    • class=”{config Class name}” 을 지정하면 자바로 설정한 javaConfig를 가져올 수 있다.
  • : ref를 생성자에 주입시킬 빈의 id를 입력한다, 리터럴 값은 value를 사용해서 입력한다.
  • : 생성자가 리스트일 경우 해당 태그안에 태그를 묶어 사용 가능하다. 객체일경우 태그도 가능
  • : resource="{config xml name}"을 통해 다른 xml config 파일을 가져올 수 있다,
환경과 프로파일
  • @Profile
    • 스프링 런타임시 환경관련 설정을 결정하는 애너테이션
    • 개발 환경인지 운영 환경인지 환경에 따라 DataSource 등 설정 클래스를 지정해준다.
    • 메소드 수준에서도 가능
    • xml 상에서는 태그로 감싸서 사용이 가능하다.
    • spring.profiles.default, spring.profiles.active 프로퍼티를 사용해 사용할 Profile를 지정한다. active가 설정되어 있지 않는 경우 default를 사용
    • web.xml default는 을 통해프로파일 설정 active는 DispatcherServlet을 통해 설정
조건부 빈
  • @Conditional
    • 소정의 조건이 참으로평가된 경우 빈이 생성된다. 그렇지 않으면 빈은 무시된다.
    • @Conditional({className}.class) « 조건적으로 빈 생성된
    • 조건적으로 빈을 생성하기 위해선 위에 {ClassName}은 Condition 인터페이스를 상속받아 구현해야 함
    • Profile을 개발 환경, 운영환경에 각각 만들고 @Conditional을 사용해 조건부 빈을 만들면 어떤 환경이 든 해당 빈을 확인 후 생성되고 각각 환경에 맞게 사용할 수 있음
  • @Primary
    • @Autowired는 한개의 빈이 있을경우 자동으로 의존성을 주입하지만 여러개의 빈이 있을 경우 오토와이어링의 모호성을 피하기 위해 지정한다.
    • 2개 이상의 빈을 기본으로 지정하면 기본 후보자가 없기때문에 문제가 발생한다.
    • @Bean, @Component 모두 사용 가능
    • XML로 빈을 설정하여 기본 빈을 지정할 수 있다.
  • @Qualitier대비해 수식자로 빈 ID에 의존하는대신 빈에 자신의 수식자를 지정한다. @Component나 @Bean 있는 곳에 수식자 id를 지정해서 클래스명이 아닌 지정한 id
    • 기본 빈은 명백한 옵션을 선택하지 못해 모호함이 남아 있을 경우 범위를 좁히기 위해사용한다.
    • @Autowired, @Inject을 사용한은 곳에 사용하여 id값을 지정하면 컴포넌트 스캔시 지정한 id에 해당하는 클래스를 찾아 파라미터 값으로 주입한다.
    • id는 대문자로 시작하지 않는 클래스 명인 빈으로 만들어진다.
    • 위 방법대로 진행시 리팩토링 및 클래스 명이 변경되면 해당 빈을 찾지 못해 에러가 발생한다 그럴경우를 값으로 구분되도록 한다.
    • 지정한 수식자가 여러개 있을 경우
    • 위에 방법도 문제가 있는 경우가 지정 id값이두개일 경우이다. 동일 애너테이션은 하나만 사용이 가능해 정의된 맞춤형 에너테이션으로 만들어 해결이 가능하다 그러면 동일한 지정 id를 가져도 에너테이션을 각각 만들어 범위를 좁힐 수있다
    • @Target({ElementType.,CONSTRUCTOR, ElementTtpe.FIELD, ElemnetType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface annatitionName {}
    • @Component 지정한 class에 만들어진 애너테이션을 적용하고 @Autowired에서도 애너테이션을 추가해 사용하면 좀 더 세부적인 구분이 가능하다.
  • @Scope
    • 기본적으로스프링 애플리케이션에서 생성되는 모든 빈은 싱글톤 이지만 재사용으로는 안전하지 않은 이변성 클래스를 사용할때 쓰인다.
    • 스프링 빈 범위
      • 싱글톤 : 전체 애플리케이션을 위해 생성되는 빈의 인스턴스
      • 프로토타입 : 빈이 주입될 때마다 생성되거나 스프링 애플리케이션 컨텍스트에서 얻는 빈의 인스턴스 하나
      • 세션 : 웹 애플리케이션에서 각 세션용으로 생성되는 빈의 인스턴스 하나
      • 요청 : 웹 애플리케이션에서 각 요청으로 생성되는 빈의 인스턴스 하나
    • @Component, @Bean 애너테이션과 관련된 다른 타입을 선택하기 위해 사용가능
    • @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) , @Scope(“prototype”)을 사용할수 있지만 상수를 사용함으로써 실수를 줄임
    • 해당 애너테이션을 통해 빈의 범위를 지정 할 수 있다.
    • XML을 사ㅏ용시
    • ex) 쇼핑몰에 장바구니 같은 경우 싱글톤으로 생성시 모든 회원이 같은 객체를 사용하므로 세션 범위를 지정해준다.
    • proxyMode=ScopedProxyMode.INTERFACES
      • 이 특성은 싱글톤 범위의 빈에 세션범위 또는 요청 범위 빈을주입할때 발생하는 문제를 해결한다.
      • 장바구니 같은 경우 모두 장바구니 객체를 하나만 사용하는 것처럼 보이지만 실제로는 사용자 별로 만들어진 장바구니 객체가 여러개 존재한다. 인터페이스 기반으로 객체를 장바구니 객체를 위입해주는 역활을 한다.
      • xml 같은 경우는 AOP 네임스페이스에서 새로운 요소를 사용해야 한다
      • prox-target-class 애트리뷰트를 false로 설정하여 인터페이스 기반의 프록시를 설정할수있따.
  • @PropertySource
    • 외부 값 주입, @PropertySource(“classpath:///*.properties”)
    • @Autowired Environment env;를 통해 값을 가져옴
플레이스 홀더
  • 자바는 configration 클래스에서 빈 지정, XML, 자바 모두 ${test.tes} 형태로 사용
SpEL
  • 스프링 표현 언어로 EL 언어 #{}를 사용하며, 프로퍼티 플레이스홀더는 ${} 사용
  • T() 클래스를 표현
  • matches 로 정규효현식 사용 가능
  • ? null 체크
  • 컬렉션
    • #{jukebox.songs[T(java.lang.Math).random() * jukebox.songs.size()].title}
    • id가 jukebox인 빈의 song 컬렉션 프로퍼티에서 무작위로하나를 선택해서 tilte을 가져온다.
    • #{‘This is a test’[3]}
    • String값의 4번째 문자를 참조한다.
    • #{jukebox.songs.?[artist eq ‘Aerosmith’]}
    • jukebox 내ㅜㅎ wjscp fltmxmdptj artist 프로퍼티가 Aerosmith인 노래 리스트를 조회하기 위한 방법
AOP(Aspect Oriented Programming), 관점 지향 프로그래밍
  • 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어보고 그 관점을 기준으로 각각 모듈화 하겠다는 것이다.
  • 모듈화를 한다는 것은 코드들을 부분적으로 나누어서 모듈화하겠다는 의미로 코드상에서 다른 부분에 계속 반복해서 쓰는 코드들을 발견할 수 있는데 이것을 흩어진 관심사(Crosscutting Concerns)라 부르며 이와 같은 흩어진 관심사를 Aspect로 모듈화하고 핵심적인 비즈니스 로직에서 분리하여 재사용하겠다는 것이다.
  • Aspect : 흩어진 관심사를 모듈화 한 것. 주로 부가기능을 모둘화함, 어드바이스와 포인트 커트를 합친 것으로 애스팩트가 무엇을 언제 어디서 할지 필요한 모든 정보가 정의된다.
  • Target : Aspect를 적용하는 곳(클래스, 매서드 ..)
  • Advice : 실질적으로 어떤 일을 언제 무엇을 해야할지에 대한것, 실질적인 부가기능을 담은 구현체
    • 이전(before) : 어드바이스 대상 메소드가 호출되기 전에 어드바이스 기능 수행하기
    • 이후(after) : 결과에 상관없이 어드바이스 대상 메소드가 완료된 후에 어드바이스 기능을 수행한다.
    • 반환 이후(after-returning) : 어드바이스 대상 메소드가 성공적으로 완료된 후에 어드바이스 기능을 수행한다.
    • 예외 발생 이후(after-throwing) : 어드바이스 대상 메소드가 예외를 던진 후에 어드바이스 기능을 수행한다.
    • 주위(around) : 어드바이스가 어브다이스 대상 메소드를 감싸서 어드바이스 대상 메소드 호출 전과 후에 몇가지 기능을 제공한다.
  • JoinPoint : 어드바이스를 적용할 수 있는 곳이며 애플리케이션 실행에 애스펙트를 끼워 넣을 수 있는 지점을 말한다. 끼워 넣을 수 있는 지점으로는 메소드 호출 지점이나 예외발생, 필드값 수정 등이 있다.
  • PointCut : 애스팩트가 어드바이스할 조인 포인트 영역을 좁히는 일, 어드바이스가 무엇을 언제 할지를 정한다면 포인트커트는 어디서 할지를 정한다. 각 포인트커트는 어드바이스가 위빙되어야 하는 하나 이상의 조인 포인트를 정의한다. 지정 방식은 클래스나 메소드명을 직접 사용하는 것이지만 매칭 패턴을 나타내는 정규 표현식을 정의하는 방법도 있다.
  • Introduction : 기존 클래스에 코드 변경 없이도 새메소드나 맴버 변수를 추가하는 기능이다. 예) 객체가 언제 변경되었는지에 대한 정보를 추가하는 경우 각 클래스에 해당 정보를 저장하는 대신 Auditable 어드바이스 클래스를 생성하여 setLastModified(Date) 메소드와 이 상태를 저장하는 멤버 변수를 정의한다. 그다음 인트로덕션을 적용하면 기존 클래스에 소스 변경없이 새로운 메소드와 멤벼 변수를 도입할 수 있다.
  • Weaving : 타깃 객체에 애스팩트를 적용해서 새로운 프록시 객체를 생성하는 절차이다. 애스펙트는 타깃 객체의 조인 포인트로 위빙된다. 위빙은 다음중 몇가지 시점에 수행된다.
    • 컴파일 시간 : 타깃 클래스가 컴파일될 때 애스팩트가 위빙되며 별도의 컴파일러가 필요하다. AspectJ의 위빙 컴파일러는 이러한 목적으로 사용된다.
    • 클래스로드 시간 : 클래스가 JVM에 로드될 떄 애스팩트가 위빙된다. 이렇게 하려면 애플리케이션에서 사용되기 전에 타깃 클래스의 바이트 코드를 인핸스 하는 특별한 ClassLoder가 필요하다 AspectJ 5의 로드 시간 위빙 기능을 사용하면 클래스로드 시간에 위빙된다.
    • 실행 시간 : 애플리케이션 실행 중에 애스팩트가 위빙된다. 보통 타깃 객체에 호출을 위임하는 구조의 프록시 객체를 위빙 중에 AOP 컨테이너가 동적으로 만들어 낸다. 스프링 AOP 애스팩트가 위빙되는 방식이다.
  • 정리 : 포인트 커트는 어드바이스 대상이 될 조인 포인트를 정의한 것이다.
Spring AOP
  • 고전적 스프링 프록시 기반 AOP가
  • Pure-POJO 애스팩트
    • aop 네임스페이스를 사용하여 POJO에서 애스팩트로 전환할 수 있다. 이러한 POJO는 포인트 커트에 대한 반응에서 호출되는 메소드들을 지원한다. XML 설정이 필요하긴 해도 객체에서 애스팩트로 전환하기 위한 가장 명확한 방법이다.
  • @AspectJ 애너테이션 기반 애스팩트
    • 스프링은 프록시 기반 AOP지만 프로그래밍 모델에서 AspectJ로 애너테이션된 애스팩트를 사용할 수 있다. 이러한 AOP 스타일의 특전은 XML 설정이 필요가 없다.
  • AspectJ 애스팩트에 빈 주입(스프링 모든 버전에서 지원)
    • 간단한 가로채기 이상(생성자 또는멤버 변수에 대한 가로치기)의 능력이 필요하다면 AspectJ를 이용하여 구현하고 AspectJ 기반 애스팩트로 값을 주입한다.
  • 스프링에서 생성하는모든 어드바이스는 표준 자바 클래스로 작성한다. 그리고 포인트 커트의 경우 어드바이스를 적용할 곳을 정의하는데 보통 스프링 XML 설정 파일에 정의하게 된다.
  • 스프링 애스팩트는 타깃 객체를 감싸는 프록시 형태로 구현된다. 이 프록시는 먼저 호출을 가로챈 후 추가적인 애스팩트로 로지글 수행하고 나서야 타깃 메소드를 호출한다.
  • 스프링은 동적 프록시를 기반으로 AOP를 구현하므로 메소드조인 포인트만 지원한다. 더 세밀한 제어가 필요하다면 그때는AspectJ를 사용한 스프링 AOP를 이용하여 보충한다.
AspectJ
  • execution 지정자만 실제로 일치시키는 작업을 수행한다. 다른 지정자는 일치를 제한하는데 사용한다. 이는 execution이 작성하는 모든 포인트 커트 정의에 사용할 기본 지정자라는 의미이다.
  • @annotation(“excution(* package.className.methodName(..)) && within(package)”)
    •   사용가능
  • @annotation(excution(* package.className.methodName(..)) and bean(‘beanName’))
    • 특정 빈을 지정해서 사용, !bean(‘beanName’)을 통해 특정 ID가 아닌 모든 빈에 애스팩트를 적용할 수 있다.
  • @Pointcut : 애스팩트에서 재사용 가능한 포인트 커트를 정의함으로 중복으로 사용하지 않을 수 있다. 메소드 몸체는 별 볼 일 없으며 실제로 비어있고 메소드 자체는 마커이다.
    • excution(* package.className.methodName(..))
  • 해당 클래스는 POJO로 애스팩트로서 사용되기 위해 애너테이션 되는 다른 자바 클래스다. 다른 자바 클래스처럼 스프링에서 빈으로 와이어링 된다.
  • 빈만 등록시 스프링 컨테이너 내의 빈일 뿐이고 Aspectj 애너테이션을 사용하더라도 애스펙트로 변경하는 프록시를 생성하고, 애너테이션을 해석하는 무엇인가 없이는 애스펙트로 취급되지 않는다.
  • JavaConfig를 사용하면 설정 클래스의 클래스 레벨에서 @EnableAspectJAutoProxy 애너테이션을 적용하여 오토 프록싱을 사용한다.
  • XML 사용시에는 를 사용하여 활성화한다. 빈등록은 기존 POJO와 동일하게 사용
  • @Around : 어드바이스된 메소드를 완전히 감싸는로직을 작성하며 단일 어드바이스 메소드 내의 before, after 어드바이스를 작성한다.
    • ProceedingJoinPoint : 파라미터로 해당 객체를 받으며 이 객체는 어드바이스 내에서 어드바이스 대상 메소드를 호출할 수 있는 방법을 제공한다.
    • 어드바이스는수행에필요한 모든 작업을 수행하고 대상 메소드에 제어를 전달할 준비가 되면 proceed() 메소드를 호출한다.
    • around 어디바이스를구현할 때는 반드시 proceed()를 호출해야 한다. 만약 호출하지 않을경우 어드바이스는 어드바이스 대상메소드에 대한 액세스를 효과적으로 막느다.
  • XML 에서 사용시에는 요소로 시작한다.
프록시 패턴
  • 프록시 패턴 기반의 AOP 구현체, 프록시 객체를 쓰는 이유는 접근 제어 및 부가기능을 추가하기 위해서이다.
  • 스프링 빈에만 AOP를 적용 가능
  • 모든 AOP 기능을 제공하는 것이 아닌 스프링loC와 연동하여 엔터프라이즈 애플리케이션에서 가장 흔한 문제(중복코드, 프록시 클래스 작성의 번거로움, 객체들 간 관계 복잡도 증가…)에 대한 해결책을 지원하는것이 목적
  • 어떤 기능을 추가하려 할때 기존 코드를 변경하지 않고 기능을 추가할 수 있다.
  • 어떤 클래스가 Spring AOP의 대상이라면 그 기존 클래스의 빈이 만들어질때 Spring AOP가 프록시(기능이 추가된 클래스)를 자동으로 만들고 원본 클래스 대신 프록시를 빈으로 등록한다. 그리고 원본 클래스가 사용되는 지점에서 프록시를 대신 사용한다. 이로 인해 개발자는 비즈니스 로직에만 집중할수 있게 된다.
AspectJ 표현식 언어
  • args() : 인자가 주어진 타입의 인스턴스인 조인 포인트 매칭을 정의한다.
  • @args() : 전달된 인자의 런타임 타입이 주어진 타입의 애너테이션을 갖는 조인 포인트 매칭을 정의한다.
  • execution() : 메소드실행 조인 포인트와 일치시키는 데 사용된다.
  • this() : AOP 프록시의 빈 레퍼런스가 주어진 타입의 인스턴스를 갖는 조인 포인트를 정의한다.
  • target() : 대상 객체가 주어진 타입을 갖는 조인 포인트를 정의한다.
  • @target() : 수행 중인 객체의 클래스가 주어진 타입의애너테이션을 갖는 조인 포인트를 정의한다.
  • within() : 특정 타입에 속하는 조인 포인트를 정의한다.
  • @within() : 주어진애너테이션을 갖는 타입 내 조인 포인트를 정의한다(스프링 AOP를 사용할 때 주어진 애너테이션을 사용하는 타입으로 선언된 메소드를 실행)
  • annotation : 조인 포인트의 대상 객체가 주어진 애너테이션을 갖는 조인 포인트를 정의한다.
AOP 어노테이션
  • @Transactional
    • JDBC에서 트랜잭션 처리를 하려면 SQL 실행문 앞뒤에 setAutoCommit()와 commit()/rollback() 코드가 항상 붙는데 프록시에 자동으로 코드를 넣어서 반복, 중복되는 코드를 생략할 수 있다.
ORM(Object Relational Mapper)
  • 자바 객체와 엔티티를 그대로 연결해주는 Mapper이다. Java 표준 orm 인터페이스 중 유명한 것은 JPA 있고 hibernate와 EclipseLink가 인터페이스의 유명한 구현체 이다.
JPA(Java Persistence API)
  • JAP란 DB 테이블과 자바 객체 사이의 매핑을 처리해주는 ORM 기술의 표준이다. 즉 자바의 클래스와 DB테이블을 매핑하는 기술
BeanFactory
  • Bean 객체를 생성하고 관리하는 인터페이스 디자인패턴의 일종인 팩토리 패턴을 구현한 것이다. BeanFactory 컨테이너는구동될떄 Bean 객체를 생성하는게 아닌 클라이언트 요청이 있을때 getBean()객체를 생성한다.
ApplicationContext
  • BeanFactory를 상송받은 인터페이스로 컨테이너는 구동되는 시점에 등록된 Bean 객체들을 스캔하여 객체화 한다.
  • 스프링 컨테이너, IoC 컨테이너라고 말하는 건 ApplicationContext 인터페이스를 구현한 클래스의 오브젝트이다.
스프링 애플리케이션
  • POJO 클래스와 설정 메타정보를 이용해 IoC 컨테이너가 만들어주는 오브젝트의 조합
WebApplicationContext
  • ApplicationContext를 확장한 인터페이스로 가장 많이 사용되는 애플리케이션 컨텍스트
  • Web에서는 서블릿 컨테이너가 브라우저로부터 오는 HTTP 요청을 받아 해당 요청에 매핑되어 있는 서블릿을 실행해주는 방식으로 동작한다. 서블릿이 일종에 main() 메소드와 같은 역활을 하는 셈이다.
  • 자신이 만들어지고 동작하는 환경인 웹 모듈에 대한 정보에 접근할 수 있다.
DispatcherServlet
  • 웹환경에서 애플리케이션 컨텍스트를 생성하고 설정 메타 정보로 초기화 해주고, 클라이언트로부터 들어오는 요청마다 적절한 빈을 찾아서 이를 실행해주는 기능을 가진다.
IoC 컨테이너 계층 구조
  • IoC 컨테이너는 애플리케이션마다 하나면 충분하지만 한 개 이상의 IoC 컨테이너를 만들경우에는 트리모양의 계층구조를 이용한다.
  • 모든애플리케이션 컨텍스트는 부모 애플리케이션 컨텍스트를 가질 수 있어 이를 이용해 트리 구조로 만든다.
  • 서블릿을 통해 요청이 들어오면 자신의 빈을 먼져 찾고 부모를 찾는다. 자신에게 해당하는 빈이 있을경우 부모는 찾지 않는다. 같은 레벨에 있는 형제는 찾지 않는다.
ServletContextListener
  • 웹 애플리케이션 레벨에 만어지는 루트 웹 애플리케이션 컨텍스트를 등록하는가장 간단한 방법이다.
  • 웹 애플리케이션 전체에 적용 가능한 DB 연결 기능이나 로깅 같은 서비스를 만드는데 쓰인다.
  • 스프링은 웹 애플리케이션의 시작과 종료 시 발생하는 이벤트를 처리하는 리스너인 ServletContextListener를 이용한다.
  • 사용방법은 web.xml 파일안에 org.springframework.web.context.ContextLoaderListener를 등록한다.
  • 별다른파라미터를 지정하지 않으면 디폴트로 다음값이 적용된다
    • 애플리케이션 컨텍스트 클래스 : XmlWebApplicationContext
    • XML 설정파일 위치 : /WEB-INF/applicationContext.xml
  • contextClass 파라미터를 이용해 지정해주면 XmlWebApplicationContext 외에 스프링에서 제공하는 다양한 컨텍스트 클래스를 이용 가능하다.
    • ex) AnnotationConfigWebApplicationCOntext : 자바 코드상에 애노테이션을 이용한 설정
스프링 MVC
  • 스프링 MVC 요청 추적
    • 요청
      • 클라이언트 화면에서(웹 화면) URL과 파라미터 값들을 같이 보내 요청
    • DispatcherServlet
      • 프런트 컨트롤러서블릿으로 실제 처리를 수행하기 위해 다른 컴포넌트에 대한 요청 책임을 위임한다.
    • 핸들러 매핑
      • 요청을 처리하기 위해 적절한 컨트롤러를 선택해줌
    • 선택된 컨트롤러
      • DispatcherServlet은 선택된컨트롤러에 요청을 보내고 컨트롤러에서 요청은 페이로드(사용자에 입력된 정보)를 떨군다.
      • 잘 디자인된 컨트롤러는 비즈니스 로직을 직접 처리기 보다는 다수의 서비스 객체에 처리를 떠넘기거나 아주 짧은 시간만을 할애한다.
      • 컨트롤러에서 처리되는 로직의 결과는 사용자의 브라우저에 표시되기 위한 형태의 정보로 반환된다.
      • 모델을 패키징하는 일과 결과물을렌더링하기 위한 뷰의 이름을 확인해 모델과 뷰 이름을 포함하여 DispatcherServlet으로 요청을 돌려보낸다
      • DispatcherServlet은 뷰 리졸버에게 논리적으로 주어진 뷰의 이름과 실제로 구현된 뷰를 매핑해 줄 것을 요청한다. 구현된 뷰는 jsp일 수도 있고 아닐 수도 있다.
DispatcherServlet
  • MVC의 핵심으로 요청을 여러 다른 컴포넌트를 통해 라우팅 한다.
  • 서블릿들은 web.xml로 설정을하지만 java를 통해 설정하기도 한다.
AbstractAnnotationConfigDispatcherServletInitializer
  • 추상 클래스로 상송받은 클래스는 DispatcherServlet과 애플리케이션의 서블릿 컨텍스트내의 스프링 애플리케이션 컨텍스트를 설정한다.
스프링 장점
  • 경량급
    • 실제로 스프링은 가벼운 프로젝트가 아닌 20여개의 세분화된 모듈로 구성되고 라인수도 수십만에 달한다. EJB는 작동을 위해서 서버(was)가 필요하며 운영 및 개발, 테스트 등이 매우 무겁고 복잡하다 이와 다르게 스프링은 불필요환 부분들이 제거되어 가볍다는 말이 나온다.
    • 경량급이라는 의미는 스프링을 기반으로 제작되는 코드가 기존 EJB나 여타 프레임워크에서 동작하기 위해 만들어진 코드에 비해 상대적으로 작고 단순하다는 뜻이다.
    • 프레임워크와 서버 환경에 의존적인 부분을 제거해 주기 때문에 반복되는 코드가 제거되고 가장 단순한 코드만 남게됬다.
  • 복잡함 해결
    • 환경이나 서버가 바뀌고 적용되는 조건이 바뀌면 적용하는 기술이달라지고 그에 따라 코드도 바뀌는건 심각한 문제를 야기한다.
    • 스프링은 서비스 추상화를 통해 로우 레벨의 기술 구현 부분과 기술을 사용하는 인터페이스를 분리, 환경과 세부기술에 독립적인 접근 인터페이스를 제공
  • 로직섞임 해결
    • 비즈니스 로직 전후로 경계가 설정되야 하는 트랜젝션, 비즈니스 로직에 대한 보안적용, 계층 사이에 주고받는 데이터와 예외의 일괄 변환이나 로깅이나 감사 등..
    • AOP를 적용하여 애플리케이션 로직을 담당하는 코드에 남아 있는 기술 관련 코드를 깔끔하게 분리해서 별도의 모듈로 관리하게 해준다.
3계층 아키텍처와 수직 계층
  • 클라이언트
  • 프레젠테이션 계층(웹, UI, MVC)
  • 서비스 계층(매니저, 비즈니스 로직)
  • 데이터 액세스 계층(DAO, EIS)
    • DB/레거시
    • 데이터 액세스 : DAO 계층으로도 불리며 장기적인 데이터저장을 목적으로 하는 DB 이용이 주된 책임이다.
Domain Models
  • Entity
    • 데이터베이스의 테이블과 1:1로 매핑되는 클래스로 테이블내에 존재하는 컬럼만을 속성으로 가져야 한다.
    • 상속을 받거나 구현체여서는 안되며, 테이블내에 존재하지 않는컬럼을 가져서도 안된다.
    • Domain Logic을가지며 Presentation Logic을 가지고 있으면 안된다.
    • 구현 method는 주로 Service Layer에서 사용한다.
    • Entity와 DTO를 분리하는 이유는 DB layer와 View Layer 사이의 역활을 분리 하기 위해서다.
  • DTO(Data transfer Object)
    • 계층간 데이터 교환을 위한 객체(java Beans)로 주로 비동기 처리를 할 때 사용한다.
    • DB의 데이터를 Service나 Controller 등으로 보낼때 사용하는 객체이다.
    • DB의 데이터가 Presentation Logic Layer로 넘어올때 DTO로 변환되어 오고가는 것이다.
    • 로직을 갖고 있지않는 순수한 데이터 객체이며, getter/setter 메서드만을 갖는다
    • Controller Layer에서 Response DTO 형태로 Client에 전달한다.
    • DTO와 VO는 동일한 개념이지만 VO는 read only 속성을 갖는다. VO는 특정한 비즈니스 값을 담는 객체이고, DTO는 Layer간의 통신 용도로 오가는 객체를 말한다.
  • VO(Value Object)
    • 값을 가지고 있는 객체
    • 핵심 역활은 equals()와 hashcode()를 오버라이딩 하는 것이다.
    • 내부에 선언된 속성의 모든 값들이 VO 객체마다 값이 같아야 똑같은 객체라고 판별한다.
    • VO는 테이블 내에 있는 속성 외에 추가적인 속성을 가질수 있으며, 여러 테이블에 대한 공통 속성을 모아서 만든 클래스를 상속받아서 사용할 수 있다.
    • Getter와 Setter를 가질 수 있다.

태그:

카테고리:

업데이트:

댓글남기기