Spring Webmvc의 핵심 엔진
Front Controller (DispatcherServlet)
IoC Container(ApplicationContext)
Inversion of control(역제어)
일반적인 명령어 실행은 위->아래로 순차적으로 실행한다. (순차적의 반대 : 역제어)
일반적인 순리는 내가 먹을 음식을 내가 재배하거나 사냥하는 것이지만 현대에 와서는 사람이 많고 분업이 가능해져서 역제어가 가능.
그래서 원래대로라면 내가 생성자에서 직접 객체를 받는게 순리이지만, @Autowired와 같은 스프링 프레임워크를 통해 외부에서 주입받을 수 있게 된 것이다.
왜 순리를 역행하냐고??????
결국 역제어가 생긴 이유는 대단위 프로젝트에서 객체관리를 효율적으로 하고 실행 흐름을 효율적으로 하기 위해서이다.
생활속의 예 : 컴퓨터(교육센터에서 주입받는다), 핸드폰(외부에서 사온다)
Event Listener
Reflection API, Annotaion 이 두가지가 뒷받침되어 FrontController, IOC Container두개가 합쳐져 Spring webMVC가 된다.
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패턴에 관한 내용으로 다음시간에 배움.
클래스파일에 남길 수 있는 주석이다.
주석의 프로퍼티를 정의할 수 있다. => 인터페이스에서 메서드를 정의하는 것과 유사하다. => 메서드 이름은 프로퍼티(변수)명처럼 작성한다. 즉 일반적인 메서드는 보통 동사로 이름을 시작하지만, 애노테이션은 명사(명사구)로 이름을 짓는다.
클래스 파일에 남길 수 있는 주석 => 형식을 갖춘 주석을 남길 수 있다. => 용도 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값을 지정할 수 있다.
annotation의 value프로퍼티는 다른 프로퍼티 값이 병렬로 들어가지 않는 이상 생략이 가능하다.
value속성이 아닌 직접 지정한 프로퍼티는 생략이 불가능!
배열 애노테이션 : 기본 값을 지정할 때 중괄호 사용
String[] v1() default {"가나다","라마바"};
애노테이션 적용 범위 : @Target을 사용하여 애노테이션을 붙일 수 있는 범위를 지정할 수 있다.
@Target({ElementType.METHOD})
: 메소드만 애노테이션을 붙일 수 있게 범위를 제한한다.
ElementType.xxx(자동완성 되는 걸 통해 무슨 타입을 지정할 수 있는지 알 수 있다.)
애노테이션을 붙일때 선언된 ElementType을 보고 붙이도록 하자.
spring-context라고 검색하면 Spring-IOC컨테이너가 나온다.
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메서드를 호출해서 객체 생성하란 뜻이다. 의미있는 메소드가 된다는 뜻 하아아아아
현업가면 어제까지 잘되던게 오늘 안될수도 있음
왜 그런일이 생기는가? 왜냐면… 주기적으로 업데이트되기때문에.. 무식하게 한줄씩 비교해서라도 찾아본다.
<bean id="c1" class="com.eomcs.spring.ioc.ex01.Car"/>
스프링IOC에보관된 객체를 꺼내서 그 이름으로 저장한다는 뜻의 application-config태그이다.
ex01의 주제 : 설정파일 다루고 설정파일에서 객체꺼내고 저장ㅈ하는 것 까지.
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
이름끝의 숫자가 늘어나는 것을 알 수 있다.
<!-- 호출할 생성자 지정하기 -->
<!-- 생성자의 파라미터 값을 주지 않으면 기본 생성자가 호출된다. -->
<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 별명은 바꿀 수 있는데 웬만해선 개성을 살리지 말고 틀대로 쓰는게 좋다.