You are using an outdated browser. Please upgrade your browser to improve your experience.

12/14

Spring Webmvc의 핵심 엔진

Spring IOC

  1. DI(의존성 주입)
  1. Event Listener

    • 순차적 : 원래대로라면 개발자가 명시적으로 메서드를 호출하는 것.(ex : project.getName())
    • contextInitialized와 같은 메서드는 서버쪽에서 호출하는 메서드이다.
    • 역제어 : 특정 상태에 놓일 때 메서드가 호출되는 것
      • 예 ) Listener의 메서드
    • 일상속의 IOC 예 : 경찰, 택시, 배달(배달 요청이 들어오면 그때 행동한다.)

Spring IOC에서 사용하는 기술

Reflection API, Annotaion 이 두가지가 뒷받침되어 FrontController, IOC Container두개가 합쳐져 Spring webMVC가 된다.


eomcs-java-basic - reflect

Class.forName(“com.eomcs.reflect.ex01.A”); 파라미터로 패키지명을 포함한 전체 클래스 이름을 지정해야 한다. 패키지명을 포함한 전체 클래스 이름 = fully qualified class name = FQName = QName

리플렉션을 쓰면 어떤클래스가 어떤 인터페이스를 구현했는지 알 수 있다~

리플렉션은 슬쩍 훑어보기! 깊게 들어가지 말자

Exam05 obj = new Exam05(); obj.minus(10, 20); // 일반적인 인스턴스 메서드 호출할 m.invoke(obj, 10, 20); // 리플렉션 API 를 사용하여 인스턴스 메서드 호출 invoke는 framework를 만들때나 쓰지 우리가 쓸 일은 없다.

파라미터값이 Class인경우 어떤 타입인지 클래스 정보를 넘기라는 뜻이다.

리플렉션 패키지를 모두 이해할 필요는 없으나 빨리 이해할수록 내 연봉이 급상승하는 지름길이다,

ex06패키지는 proxy패턴에 관한 내용으로 다음시간에 배움.

annotation

클래스파일에 남길 수 있는 주석이다.

주석의 프로퍼티를 정의할 수 있다. => 인터페이스에서 메서드를 정의하는 것과 유사하다. => 메서드 이름은 프로퍼티(변수)명처럼 작성한다. 즉 일반적인 메서드는 보통 동사로 이름을 시작하지만, 애노테이션은 명사(명사구)로 이름을 짓는다.

클래스 파일에 남길 수 있는 주석 => 형식을 갖춘 주석을 남길 수 있다. => 용도 1) 소스 코드에서 특정 값을 쉽게 추출할 수 있다. => 소스 코드에서 이 주석을 읽어 다른 소스 파일을 생성할 때 사용한다. 2) .class 파일에 주석을 남길 수 있다. => 실행 시에 추출하여 사용할 수 있다.

애노테이션은 일반 문장 앞에는 선언할 수 없다!

애노테이션 유지 정책

애노테이션의 유지 정책을 지정하지 않으면 기본이 class이다.

=> 컴파일 할 때 .class파일에 포함된다.

=> 단, 리플렉션 API에서 추출할 수 없다.

애노테이션 유지 정책을 SOURCE라고 지정하면 해당 애노테이션은 컴파일할 때 제거된다.

애노테이션 유지 정책을 RUNTIME라고 지정하면 해당 애노테이션은 .class 파일에 포함된다. 실행 중에 리플랙션 API로 추출할 수 있다.

// 애노테이션 사용
// => @애노테이션이름(프로퍼티명=값, 프로퍼티명=값, ...)
//
package com.eomcs.annotation.ex2;

@MyAnnotation(value="값") // 유지정책 => CLASS 
@MyAnnotation2(value="값") // 유지정책 => SOURCE 
@MyAnnotation3(value="값") // 유지정책 => RUNTIME 
public class MyClass {
}

.class파일

// Compiled from MyClass.java (version 11 : 55.0, super bit)
@com.eomcs.annotation.ex2.MyAnnotation(value="값")
@com.eomcs.annotation.ex2.MyAnnotation3(value="값")
public class com.eomcs.annotation.ex2.MyClass {
  

MyAnnotation을 추출할 수 없습니다! MyAnnotation2를 추출할 수 없습니다! MyAnnotation3.value=값

실행결과에서 MyAnnotation을 추출할 수 없는건 리텐션 정책이 class로 선언되었기 때문이다.

인터페이스와 애노테이션이 유사성을 띄지만 애노테이션에서는 프로퍼티의 default값을 지정할 수 있다.

배열 애노테이션 : 기본 값을 지정할 때 중괄호 사용

String[] v1() default {"가나다","라마바"};

애노테이션 적용 범위 : @Target을 사용하여 애노테이션을 붙일 수 있는 범위를 지정할 수 있다.

@Target({ElementType.METHOD}) : 메소드만 애노테이션을 붙일 수 있게 범위를 제한한다.

ElementType.xxx(자동완성 되는 걸 통해 무슨 타입을 지정할 수 있는지 알 수 있다.)

애노테이션을 붙일때 선언된 ElementType을 보고 붙이도록 하자.

spring-context라고 검색하면 Spring-IOC컨테이너가 나온다.


Spring IOC - java basic ex01

image

image

1) 자바 CLASSPATH 에서 설정 파일을 찾는 IoC 컨테이너 => 자바 CLASSPATH? 예를 들면 /Users/eomjinyoung/git/bitcamp-study/java-basic/bin/main 즉, JVM이 자바 클래스 파일(.class)을 로딩하기 위해 찾는 경로이다. 보통 JVM을 실행할 때 -classpath 옵션이나 -cp 옵션으로 경로를 지정한다. 물론 JVM이 클래스 파일을 찾을 JVM의 기본 경로($JAVA_HOME/lib)를 가장 먼저 뒤진다. => 설정 파일 경로를 지정할 때 자바 패키지 경로를 지정한다. 파일 경로이기 때문에 패키지와 패키지 사이에는 . 대신에 /를 사용해야 한다.

만약 classpath가 아닌 다른 폴더에 설정파일이 있을 경우 file://경로.....로 일일이 지정해주어야 한다. -> 개무식한 방법이니 쓰면 안됌!!!!

현업에서 가장 많이쓰는 XML설정파일은 이것이다.

    // 3) 자바 클래스 파일의 애노테이션으로부터 설정 정보를 추출한다.
    // => 자바 클래스로 설정 정보를 다루는 것을 'Java Config' 라 부른다.
    // => 생성자 파라미터로 Java Config 클래스의 타입 정보를 넘긴다.
    ApplicationContext iocContainer = new AnnotationConfigApplicationContext(//
        AppConfig.class);

    System.out.println("실행 완료!");
    

다만 현업에서 내가 유지보수할 파일은 현재 자바프로젝트일 것이다.

appConfig = com.eomcs.spring.ioc.ex01.d.AppConfig

Appconfig파일의 이름을 소문자로 따 클래스 이름으로 지정한다.

AnnotationConfigApplicationContext를 사용하면 자동으로 필요한 객체들을 생성하기 때문에 bean의 개수가 기본적으로 4개이다.


  // 객체 생성
  @Bean
  public Car c1() {
    return new Car();
  }

@Bean을 붙이면 c1메서드를 호출해서 객체 생성하란 뜻이다. 의미있는 메소드가 된다는 뜻 하아아아아

현업가면 어제까지 잘되던게 오늘 안될수도 있음

왜 그런일이 생기는가? 왜냐면… 주기적으로 업데이트되기때문에.. 무식하게 한줄씩 비교해서라도 찾아본다.

image

<bean id="c1" class="com.eomcs.spring.ioc.ex01.Car"/>

스프링IOC에보관된 객체를 꺼내서 그 이름으로 저장한다는 뜻의 application-config태그이다.

ex01의 주제 : 설정파일 다루고 설정파일에서 객체꺼내고 저장ㅈ하는 것 까지.

spring ioc ex02

bean태그 사용하기

최신버전 사용한다고 다 되는게 아니라 내가 유지보수할건 몇번째 버전일지 모르니까 다 알아둬야해!

    <!-- id: 빈의 이름. 생성된 객체를 컨테이너에 보관할 때 사용할 key.
         class: 빈의 클래스명. 생성할 객체의 클래스 정보. 
         반드시 fully-qualified class name(FQName, QName) 이어야 한다.
         =>  Spring IoC 컨테이너는 기본 생성자를 호출하여 객체를 생성한다.
    -->
    <bean id="c1" class="com.eomcs.spring.ioc.ex02.Car"></bean>

반드시 풀패키지명을 지정해주도록 한다.

bean이 적혀있다면 그 태그에게 내리는 명령 : car라는거 만들어서 c1이라는 객체에 저장해!!@!!!!!!!!

id따로 별명따로 줄 수 있다.

    <!-- name: 빈의 별명 -->
    <bean id="c2" name="c3" class="com.eomcs.spring.ioc.ex02.Car"/>   

name속성에 여러개의 별명을 줄 수도 있으나 공백, ,콤마, ;세미콜론으로 해줄 수 있으나 보편적으로 공백을 많이 쓴다. 그러니까 그냥 공백쓰자.

그러나!!!!!!!!!!!!! 헷갈리기 쉬우니 id아니면 name 둘 중 하나만 지정하자!!!!!!!!!!!

ID든 name(별명)이든 객체를 꺼낼 때는 아무거나 상관 없음!!

빈 생성 정책

scope 속성에 빈의 생성 정책을 지정할 수 있다. => singleton: 한 개의 객체만 생성. 지정하지 않으면 기본이 singleton이다. => prototype: getBean() 호출할 때마다 생성 => request: (웹) 요청이 들어올 때마다 생성 => session: (웹) 세션이 생성될 때마다 생성 => application: (웹) 애플리케이션을 시작할 때 생성 => websocket: (웹) 웹소켓이 연결될 때 생성

우리는 싱글톤만 잘 기억하면 된다. 기본이 싱글톤임

prototype : 객체를 매번 생성한다 : 가비지 생성 매우 많음 -> 잘 쓰지 않음!

FrontContoller는 내부적으로 IOC 컨테이너를 사용한다.

<!-- 빈의 이름을 지정하지 않을 경우 
     => FQName과 인덱스 번호가 객체의 이름으로 사용된다.
     => FQName#인덱스번호
     => 예) com.eomcs.spring.ioc.ex02.Car#0
     => 익명 객체의 수 만큼 인덱스 번호가 증가한다.
-->

 <bean class="com.eomcs.spring.ioc.ex02.Car"/>
    <bean class="com.eomcs.spring.ioc.ex02.Car"/>
    <bean class="com.eomcs.spring.ioc.ex02.Car"/>
    <bean class="com.eomcs.spring.ioc.ex02.Car"/>

com.eomcs.spring.ioc.ex02.Car#0 com.eomcs.spring.ioc.ex02.Car#1 com.eomcs.spring.ioc.ex02.Car#2 com.eomcs.spring.ioc.ex02.Car#3

이름끝의 숫자가 늘어나는 것을 알 수 있다.

ex03

    <!-- 호출할 생성자 지정하기 -->
    
    <!-- 생성자의 파라미터 값을 주지 않으면 기본 생성자가 호출된다.  -->
    <bean id="c1" class="com.eomcs.spring.ioc.ex03.Car"/>

spring ioc는 생성자를 고를때 파라미터값을 가지고 판단하는데 파라미터를 명시하지 않으면 보통은 String을 우선하여 생성한다.

강사님 추천 방법

    <bean id="c10" class="com.eomcs.spring.ioc.ex03.Car">
        <constructor-arg index="1">
            <value type="java.lang.String">소나타</value>
        </constructor-arg>
        <constructor-arg index="0">
            <value type="int">1980</value>
        </constructor-arg>
    </bean>

하지만 더 추천하는 방법 : 중복되는 생성자 만들지 않기

c:파라미터명=”값” 이 방식으로는 타입을 지정할 수 없다. 그냥 IoC 컨테이너에게 적절한 생성자를 호출하도록 맡겨야 한다.

앞의 c 별명은 바꿀 수 있는데 웬만해선 개성을 살리지 말고 틀대로 쓰는게 좋다.