2018년 4월 3일 화요일

Spring 및 Annotation

1. Spring

  • SPRING
    • 원하는 부분만 가져다 사용할 수 있도록 모듈화가 잘 되어있다.
    • IOC컨테이너다(제어의 역전) : 개발자가 제어 하는 것이 아니라 다른 프로그램이 그흐름을 제어 하는것
    • DI와 인터페이스 지향을 통한 느슨한 결합도
    • 선언적으로 트랜잭션을 관리할 수 있다.
    • 완전한 기능을 갖춘 MVC Framework를 제공한다.
    • AOP와 공통 규약을 통한 선언적 프로그래밍
    • 템플릿을 통한 상투적인 코드 축소
    • 스프링은 도메인 논리 코드와 쉽게 분리될 수 있는 구조를 가지고 있다.
    • POJO를 이용한 가볍고 non-invasive(비 침투적) 개발
    • POJO : 다른 라이브러리 및 소스에 의존적이지 않은 CLASS
    • 트랜잭션을 관리할 수 있다.
    • AOP와 공통 규약을 통한 선언적 프로그래밍
    • 원스-스탑-숍(One-Stop-Shop): 모든 과정을 한꺼번에 해결하는 상점
    • EJB :  생성, 관리, 컨테이너  
    • Bean : 인스턴스생성, 관리 , 컨테이너에 의해 관리되는 객체(개발자가 직접 생성하는 객체는 Bean이 아니다)
  • 레이어드 아키텍처(Layered architecture)
    • 중복된 화면 및 소스를 활용하기 위해서 3단계로 나눠서 구현한다.
    • @Controller -> @Service -> @Repository
    • 프리젠테이션 레이어 - 비지니스 레이어(메소드:트랜잭션단위) - 데이터 레이어
      (Controlller / Service / Repository, DAO)
    • presentation layer - business layer - persistence layer - Database layer
    • 어디에도 속하지 않는 레이어는 Component라고 부른다.(persistence layer)
  • Spring Container
    • 인스턴스의 생명주기를 관리한다.
    • 생성된 인스턴스들에게 추가적인 기능을 제공한다.
  • IOC
    • 다른 프로그램에 그 흐름을 제어하는 것
  • IOC 컨테이너
    • BeanFactory <- ApplicationContext <- WebApplicationContext
    • BeanFactory
      • 빈 객체에 대한 생성과 제공을 담당
      • 단일 유형의 객체를 생성하는 것이 아니라, 여러 유형의 빈을 생성,제공
      • 객체 간의 연관 관계를 설정, 클라이언트의 요청 시 빈을 생성
      • 빈의 라이플 사이클을 관리
      • 필요할때 마다 빈 정보를 메모리에 로딩함
    • ApplicationContext
      • BeanFactory가 제공하는 모든 기능 제공
      • 엔터프라이즈 애플리케이션을 개발하는데 필요한 여러 기능을 추가함
      • L18N, 리소스 로딩, 이벤트 발생 및 통지
      • 컨테이너 생성시 모든 빈 정보를 메모리에 로딩함
    • WebApplicationContext
      • 웹 환경에서 사용할 때 필요한 기능이 추가된 애플리케이션 컨텍스트
      • 가장 많이 사용하며, 특히 XmlWebApplicationCOntext를 가장 많이 사용
  • POJO
    • Plain Old Java Object(다른 클래스에게 종속적이지 않은 클래스)
  • DI
    • 의존성 주입(A가 B를 가진다)
    • 클래스 사이의 의존 관계를 빈설정 정보를 바탕으로 컨테이너가 자동으로 연결해주는 것
  • ApplicationContext
    • AnnotationConfigApplicationContext - 하나 이상의 Java Config 클래스에서 스프링 애플리케이션 컨텍스트를 로딩(최신프로젝트에 사용 추천)
    • AnnotationConfigWebAlicationContext - 하나 이상의 Java Config 클래스에서 웹 애플리케이션 컨텍스트를 로딩(기존프로젝트들이 많이 되어있음)
    • ClassPathXmlApplcationContext - 클래스패스에 위치한 xml파일에서 컨텍스트를 로딩
    • FileSystemXmlApplicationContext - 파일 시스템에서 지정된  xml파일에서 컨텍스트를 로딩
    • XmlWebApplcationContext - 웹 애플리케이션에 포함된 xml파일에서 컨텍스트를 로딩
  • BEAN
    • 기본 scope는 싱글톤인데 메모리가 올라갈때 생성한다.(하나의 객체)
    • scope="prototype" 가 있으면 필요 할때 마다 생성된다.(매번 새로운 객체가 생성)
  • XML
    • Data를 표현한다.
    • 문서의 형식을 지정하는 방법
      • dtd
      • xml스키마
    • 자주쓰는 네임스페이스는 생략 가능하다.
    • xml문서를 읽어들이는 파서는 네임스페이스(ns)에 따라서 스키마에 맞는지 검사를 한다.
      <상품:상품 xmlns:상품="url주소" xmlns:회사="url주소">
          <상품:이름>맥북프로</상품:이름>
          <상품:가격>200</상품:가격>
          <회사:회사>
              <회사:이름>apple</회사:이름>
              <회사:가격>30</회사:가격>
          </회사:회사>
      </상품:상품>
    • schemaLocation에 설정된 주소에 설정된 정보에 따라서 파서가 작동한다.
  • 스프링과 강력한 관계를 맺고 작동시킬려고 할때 스프링에서 제공 해주는 기능
    • implements BeanNameAware
      • bean의 이름을 가지고 오려고 할때 사용
    • implements BeanFactoryAware
      • BeanFactory에서 bean을 가지고오려고 할때 사용
  • 컨테이너의 스펙 표준
    • JSR-250(자바플랫폼 공통 애노테이션)

2. Annotation

  • JUNIT Annotation
      • @RULE
        • 테스트 메소드 호출을 가로 채고 테스트 메소드가 호출되기 전과 테스트 메소드가 호출 된 후에 특정 기능을 지원 해준다.
          • TemporaryFolder : 테스트 메소드 내에서만 사용 가능한 임시 폴더나 임시 파일을 만들어준다.
          • ExternalResource : 외부 자원을 명시적으로 초기화
          • ErrorCollector : 테스트 실패에도 진행할 수 있게 해준다.
          • Verifier : 테스트 케이스와는 별개의 조건을 만들어서 확인할 때 사용한다.
          • TestWatchman : 테스트 실행 중간에 사용자가 끼어들 수 있게 도와준다.
          • TestName : 테스트 메소드의 이름을 알려준다.
          • Timeout : 일관적인 타임아웃을 설정한다.
          • ExpectedException : 테스트 케이스 내에서 예외와 예외 메시지를 직접 확인 할 때 사용.
        • System.out.println(값) 으로 출력한 결과를 가질 수 있다.
          public final StandardOutputStreamLog log = new StandardOutputStreamLog();
      • @RunWith(SpringJUnit4ClassRunner.class)
        • junit이 실행하면서 @Test할때 내부적으로 ApplicationContext를 생성한다. 
    • Spring Annotation
      • AnnotationConfigApplicationContext
        • @Configuration, @Bean이 선언이 되어있는 부분 읽어서 빈을 생성해준다.
      • @Bean
        • Bean 생성을 하는 메소드는 @Bean이 붙어야 한다.
        • 메소드이름이 아이디가 된다.
      • @Configuration
        • 이 클래스가 설정파일이라는점을 명시한다.
      • @ContextConfiguration
        • ApplicationContext가 생성할때 '클래스이름-context-xml'파일을 설정파일로하여 읽어들이도록한다. ex) 클래스명-context.xml 
      • @Autowried
        • 자동으로 해당 타입의 Bean을 DI한다(의존성 주입)
        • ApplicationContext가 관리하는 Bean중에서 해당 타입의 객체를 주입
      • @Qualifier(메소드명)
        • 메소드가 2개 이상일 경우 어노테이션이 우선순위를 가진다.
      • @RunWith(SpringJUnit4ClassRunner.class) 와 @ContextConfiguration을 설정을 CNamespaceReferenceTest class에 선언되어 있다면 ApplicationContext가 context = new ClassPathXmlApplicationContext("CNamespaceReferenceTest-context.xml") 와 같다.
      • @Scope("prototype")
        • get Bean할때마다 새로운 객체가 호출된다.
      • @ContextConfiguration(classes=클래스명.class)
        • classes에 선언된 클래스의 bean
      • @Component
        • @Controller, @Service , @Repository를 다 포함하고 있다.
      • @ComponentScan
        • 패키지 설정이 안되어있으면 현재 선언된 파일있는 패키지 기준 이하에서 @Controller, @Service , @Repository @Component 가 설정된 부분을 다 찾아서 메모리에 올린다.
      • @Autowried
        • 해당 타입의 객체를 찾아서 자동으로 대입해준다.
        • 기본생성자가 없을 경우 스프링은 최대한 파라미터에 값을 넣어서 인스턴스 생성을 하려고 노력한다.  Spring 4.1부터는 생성자에 @Autowried를 안붙여도, 자동으로 주입을 한다.
        • @Autowried @Qualifier("이름") 는 @Resource(name = "이름") 와 똑같이 작동한다.
        • @Resource은 스프링이 제공해주는것이 아니다.(JSR-250의해 만들어진 어노테이션)
      • @bean 설정에서 객체를 new 객체() 로 넘겼을때 알아야 할 내용
        • Bean을 생성하는 메소드는 예를 들어 myDisc()는 2번째 호출될 경우에는 이미 생성된 MyDisc 객체를 리턴한다. 
        • 아래와 소스를보고 mydisc == disc 의 객체가 일치하는지 예측해보자.
          mydisc와  disc을 부분을 보면 new 객체를 각각 리턴 받는다. 우리가 JAVA를 배우면서 new객체는 새로운 객체를 생성한다고 배웠다.
          그런데 콘솔을 확인해보면 생성자 부분은 1번만 실행되고 'myDisc == disc' 부분이 출력되는것을 확인 할 수 있다. class가 그대로 쓰이는게 아니고 reflection proxy , cgLIB 에 의해 컨트롤 되어서 그렇다.
        package soundsystem;
        
        import org.springframework.context.ApplicationContext;
        import org.springframework.context.annotation.AnnotationConfigApplicationContext;
        
        public class SpringExam02 {
            public static void main(String[] args) {
                ApplicationContext context =
                        new AnnotationConfigApplicationContext(CDPlayerConfig2.class);
        
                CompactDisc mydisc = context.getBean("myDisc", CompactDisc.class);
                CDPlayer cdPlayer = context.getBean(CDPlayer.class);
                CompactDisc disc = cdPlayer.getCompactDisc();
        
                if(mydisc == disc){
                    System.out.println("myDisc == disc");
                }else{
                    System.out.println("myDisc =! disc");
                }
        
        
            }
        }
        
        
        package soundsystem;
        
        public class CDPlayer implements MediaPlayer {
          private CompactDisc cd;
        
          public CDPlayer(CompactDisc cd) {
            System.out.println("CDPlayer(CompactDisc) 호출");
            this.cd = cd;
          }
        
          public CompactDisc getCompactDisc() {
            return cd;
          }
        
          public void play() {
            cd.play();
          }
        
        }
        
        
        package soundsystem;
        
        public interface MediaPlayer {
        
          void play();
        
        }
        
        
        package soundsystem;
        
        public interface CompactDisc {
        
          void play();
        
        }
        
        
        
        package soundsystem;
        
        public class MyDisc implements CompactDisc{
        
            public MyDisc(){
                System.out.println("MyDisc 호출!!!");
            }
        
            @Override
            public void play() {
                System.out.println("MyDisc!!!");
            }
        }
        
        
        
        package soundsystem;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        
        //java config 클래스에는 @Configuration 이 클래스위에 있어야 한다.
        @Configuration
        public class CDPlayerConfig2 {
        
          // Bean을 생성하는 메소드는 예를 들어 myDisc()는 2번째 호출될 경우에는 이미 생성된 MyDisc()를 리턴한다.
          @Bean
          public CDPlayer cdPlayer() {
            System.out.println("cdPlayer() 호출");
            return new CDPlayer(myDisc());
          }
        
          // 메소드 이름이 id가 된다. 메소드 이름이 중복되면 id가 중복된다는 의미기때문에 안된다.
          // <bean id="conpacDisc" class="soundsystem.SgtPeppers" />
          // Bean 생성을 하는 메소드는 @Bean이 붙어야 한다.
          @Bean
          public CompactDisc compactDisc() {
            System.out.println("compactDisc() 호출");
            return new SgtPeppers();
          }
        
          @Bean
          public CompactDisc myDisc(){
            System.out.println("-----------------------");
            System.out.println(getClass().getName());
            System.out.println("myDisc() 호출");
            System.out.println("-----------------------");
            return new MyDisc();
          }
        
        }
      • @Qualifier
        • cdPlayer 메소드를 보면 SgtPeppers 객체가 주입될것처럼 보이지만 @Qualifier 을 선언하면 우선순위에 우위를 가져서 MyDisc 객체가 주입된다.
        
        package soundsystem;
        import org.springframework.beans.factory.annotation.Qualifier;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        
        //java config 클래스에는 @Configuration 이 클래스위에 있어야 한다.
        @Configuration
        public class CDPlayerConfig3 {
        
          //파라미터 이름에 해당하는 메소드 이름이 있어도 @Qualifier("myDisc") 이 우선한다. (이긴다!)
          @Bean
          public CDPlayer cdPlayer(@Qualifier("myDisc")CompactDisc compactDisc) {
            System.out.println("cdPlayer() 호출");
            return new CDPlayer(compactDisc);
          }
        
          //메소드 이름이 id가 된다. 메소드 이름이 중복되면 id가 중복된다는 의미기때문에 안된다.
          // 
          // Bean 생성을 하는 메소드는 @Bean이 붙어야 한다.
          @Bean
          public CompactDisc compactDisc() {
            System.out.println("compactDisc() 호출");
            return new SgtPeppers();
          }
        
          @Bean
          public CompactDisc myDisc(){
            System.out.println("-----------------------");
            System.out.println(getClass().getName());
            System.out.println("myDisc() 호출");
            System.out.println("-----------------------");
            return new MyDisc();
          }
        
        } 
      • @Import
        • 외부에 있는 config 파일을 사용한다.
        • @Import(testConfig.class)
      • @ImportResource
        • 외부에 있는 설정파일을 사용한다
        • @ImportResource(classpath:test-config.xml)
      • @RequestHeader  
        • 요청정보중에서 헤더값을 읽을떄 사용
        • @RequestHeader(value="User-Agent", defaultValue="myBrowser") String userAgent
      • @GetMapping(path="/userform") (버전 4.3이상)
        • @RequestMapping(path="/userform", method=RequestMethod.GET) 와 같다.
      • @GetMapping("/goods/{id}") 
        • id부분은 가변적으로 사용할수 있다.
        • {id} 부분을 @PathVariable 이라 부른다.
      • @PathVariable
        • path의 일부분을 읽어들일 때 사용
        • @GetMapping("/test/{id}") 일때 @PathVariable(name="id") int id 로 값을 얻을수 있다.
      • @Controller의 메소드 인수 타입
        • 지원하는 타입들은 dispatcherservlet이 자동으로 넣어준다.
        • javax.servlet.http.HttpServlet등등 
      • @RestController
        • spring 4.0 이전에는 다음의 애노테이션을 붙였다.
          • @Controller
          • @ResponseBody
        • @Controller가 붙은 클래스의 메소드가 리턴하는 것은 view 이름이었다. @Controller, @ResponseBody가 붙어있을 경우에는 리턴하는 값이 출력값이다. 
        • 객체를 브라우저에게 알맞게 출력하기 위해서 사용하는 것이 MessageConverter다. 빈으로 여러개가 등록되어있다. Spring boot에서는 기본으로 설정되어 있다. 하지만 맘에안들때가 있으면 사용자가 바꿔야 한다.
      • @RequestParam
        • 클라이언트가 보내는 파라미터를 변수에 담을수 있다.
        • defaultValue 옵션을 통해 값이 없을때 기본값을 지정할 수있다.
        • 필수여부를 설정할수 있다.
        • required 옵션은 필수값 여부이다.
        • defaultValue는 값이 없을때 기본값 여부이다.
        • @RequestParam(name = "value", required = true, defaultValue = "1") int value
      • lombok Annotation
        • 컴파일 전에 자동으로 코드를 생성한다.
        • @Setter : setter메소드를 생성
        • @Getter : getter메소드를 생성
        • @ToString : toString() 메서드를 생성
        • @AllArgsConstructor : 필수 생성자를 생성
        • @NoArgsConstructor : 인자 없는 생성자 생성
        • @ModelAttribute
          • 클라이언트가 보내는 파라미터를 자바 객체로 받을수 있게 해준다.
          • 객체를 하나 만들고 set, get 메소드를 만든다.
          • 사용하려는 메소드에서 생성한 객체를 사용하고 어노테이션을 명시하면 jsp에서 'blod.name' 등으로 사용이 가능하다.
          
          public String input(@ModelAttribute Blod blod, ModelMap modelMap){
          
             return "blodResult";
          }
          
          
          public class Blod {
              private String name;
              private String blod;
              private String msg;
          
              public String getMsg() {
                  return msg;
              }
          
              public void setMsg(String msg) {
                  this.msg = msg;
              }
          
              public String getName() {
                  return name;
              }
          
              public void setName(String name) {
                  this.name = name;
              }
          
              public String getBlod() {
                  return blod;
              }
          
              public void setBlod(String blod) {
                  this.blod = blod;
              }
          
              @Override
              public String toString() {
                  return "Blod{" +
                          "name='" + name + '\'' +
                          ", blod='" + blod + '\'' +
                          ", msg='" + msg + '\'' +
                          '}';
              }
          }

      viewname 설정에 따른 redirect 와 forward

      • 단순 view name을 리턴하면 forward 처리
      • redirect:뷰네임 으로 사용하면 redirect처리가 된다.
      
      @GetMapping(value = "/")
          public String index(){
              return "redirect:/boards";
          }
      
      
      @GetMapping(value = "/")
          public String index(){
              return "boards";
          }

      http method(Rest API - WEB API(HTTPAPI))

      • GET - 정보를 요청, header로 전달이 된다. body로는 전달이 안된다.
      • POST - 등록 
      • PUT - 수정 
      • DELETE - 삭제
      • 초창기 서블릿은 get, post 있었다.

      JSP

      • 결과를 출력 JSTL & EL
      • was에 올라갈때만 실행된다.
      • jstl 사용하려면 라이브러리를 지정해줘야 한다.

      WebMvcConfigurerAdapter

      • https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.html
      • Deprecated.
        as of 5.0 WebMvcConfigurer has default methods (made possible by a Java 8 baseline) and can be implemented directly without the need for this adapter
        (스프링 5.0 부터는 WebMvcConfigurerAdapter를 사용하지 않는다. )
      • DispatcherSerlvet는 자동으로 WebMvcConfigurer를 읽는다. 그래서 WebMvcConfigurerAdapter 클래스를 구현하고 사용자는 Adapter를 상속받아서 오버라이딩해서 원하는 메소드만 구현한다.
      • 스프링 5.0부터는 JDK 1.8부터 가능하다. WebMvcConfigurer를 바로 구현해서 사용한다.(인터페이스에 default 메소드를 가질수 있어서)
      Share:

      0 개의 댓글:

      댓글 쓰기