Doc: Add Documents

main
Jooho Yoon 4 years ago
parent 27a0eaa5ae
commit f09ee60457

@ -0,0 +1,199 @@
# `@Configuration `설정과 `@Bean `등록
## 기본 규칙
>1. 환경설정 역할을 하는 클래스에 `@Configuration`을 붙여준다.
>2. @Bean 을 붙여서 등록하고자 하는 Spring Bean을 정의한다.
> * 메소드 정의시 @Bean 을 붙인다.
>3. XML Bean 설정 방법을 따른다.
> * 메소드의 Return 타입은 Bean의 Class Type 이다.
> * 메소드의 이름이 Bean의 이름(XML 설정 당시 id 속성)이다.
>
>4. 특정 Bean을 Injection 받아서 Bean을 생성해야 할땐 특정 Bean을 생성하는 메소드를 직접 호출, 메소드의 파라미터, 또는 클래스레벨의 @Autowired로 특정 Bean을 Injection 받을 수 있다
### 1. 환경설정 역할을 하는 클래스에 `@Configuration`을 붙여준다.
`@Configuration` (org.springframework.context.annotation)을 붙이면 Spring은 일반 비지니스 Bean과는 달리 설정과 관련된 Bean이라 인식한다. XML 설정에서 `<Bean>` 과 같다.
<Java Code>
```java
@Configuration
public class ContextApp {
}
```
### 2. `@Bean` 을 붙여서 등록하고자 하는 Spring Bean을 정의한다.
<XML>
```xml
<bean id="egovHandler" class="egovframework.com.cmm.EgovComExcepHndlr" />
```
#### 메소드 정의시 @Bean 을 붙인다.
해당 `<bean>`은 Java code의 메소드로 생성할 수 있으며, 해당 메소드에 @Bean을 붙여줌으로 bean 등록한다.
<Java Code>
```java
@Bean
public EgovComExcepHndlr egovHandler() {
EgovComExcepHndlr egovComExcepHndlr = new EgovComExcepHndlr();
return egovComExcepHndlr;
}
```
### 3. XML Bean 설정 방법을 따른다.
#### 메소드의 Return 타입은 Bean의 Class Type 이다.
xml 설정에서 `class``<bean>`의 타입이다. `<bean>` 태그의 필수 속성은 class 속성 하나 뿐이다. 해당 `<bean>`의 타입을 객체 생성하여 return 해 준다.
#### 메소드의 이름이 Bean의 이름(XML 설정의 id 속성)이다.
`id``<bean>``id`를 통해 참조할 경우가 있는 경우에만 설정되며 `<bean>`의 고유한 이름이 된다. 이를 Java Code에서는 메소드 이름으로 작성을 한다.
#### 프로퍼티 주입 - ` <property>`는 멤버 변수를 등록할때 사용된다.
`<property>`는 setter로 등록하는 멤버변수의 항목들이다.
#### 프로퍼티 주입 - ` <value>`는 값을 주입 할때 사용 된다.
` <value>`는 값을 주입 할 때 사용되며, `<property>`의 속성으로 사용 될 수 도 있고, 하위 태그로도 사용 될 수 있다.
#### 프로퍼티 주입 - ` <ref>`는 타입을 참조 할 때 사용된다.
`<ref>` 기존에 설정된 bean을 참조 할 수 있다.
#### 프로퍼티 주입 - collection 을 주입 할 수도 있다.`<list>`,`<set>`,`<map>`
<XML>
```xml
<bean id="defaultExceptionHandleManager" class="egovframework.rte.fdl.cmmn.exception.manager.DefaultExceptionHandleManager">
<property name="reqExpMatcher">
<ref bean="antPathMatcher"/>
</property>
<property name="patterns">
<list>
<value>**service.impl.*</value>
</list>
</property>
<property name="handlers">
<list>
<ref bean="egovHandler" />
</list>
</property>
</bean>
```
Exception 발생에 대한 기본 Exception 처리를 위해 표준프레임워크 실행환경의 ExceptionTransfer를 활용하도록 설정하고 있다. ExceptionHandlerService의 구현체를 대상으로 하고 있으며 여기서는 DefaultExceptionHandleManager을 통해 이루어 진다. 이때 생성하려는 `defaultExceptionHandleManager` bean의 class type 인 `DefaultExceptionHandleManager`을 살펴보면 `AbstractExceptionHandleManager `를 상속하고 `ExceptionHandlerService`를 구현하고 있는 것을 확인 할 수 있다.
```java
public class DefaultExceptionHandleManager extends AbstractExceptionHandleManager implements ExceptionHandlerService {
...
}
```
`AbstractExceptionHandleManager ` 를 확인 해 보면 `patterns`, `handlers`
```java
public abstract class AbstractExceptionHandleManager {
@Resource(name = "messageSource")
protected MessageSource messageSource;
...
protected String[] patterns;
protected ExceptionHandler[] handlers;
protected PathMatcher pm;
...
public void setPatterns(String[] patterns) {
this.patterns = patterns;
}
public void setHandlers(ExceptionHandler[] handlers) {
this.handlers = handlers;
}
}
```
`ExceptionHandlerService`에서 `setReqExpMatcher` 를 확인 할 수 있다.
```java
public interface ExceptionHandlerService {
...
public void setReqExpMatcher(PathMatcher pm);
...
}
```
해당 클래스 타입을 참고하여 아래와 같이 Java Code로 변환해 준다.
<Java Code>
```java
@Bean
public DefaultExceptionHandleManager defaultExceptionHandleManager(AntPathMatcher antPathMatcher, ExceptionHandler egovHandler) {
DefaultExceptionHandleManager defaultExceptionHandleManager = new DefaultExceptionHandleManager();
defaultExceptionHandleManager.setReqExpMatcher(antPathMatcher);
defaultExceptionHandleManager.setPatterns(new String[] {"**service.impl.*"} );
defaultExceptionHandleManager.setHandlers(new ExceptionHandler[] {egovHandler});
return defaultExceptionHandleManager;
}
```
`setReqExpMatcher`에 주입하는 `antPathMater` 은 context-common.xml에서 등록한 Bean으로 여기서는 파라미터로 주입받고 있다.
`setPatterns`에는 `String`타입으로 `egovHandler` 를 수행할 패턴을 지정해 주고 있다.
`setHandlers`에는 처리할 `ExceptionHandler`구현체를 리스트 형태로 넣어 줄 수 있다.
### 4. 특정 Bean을 Injection 받아서 Bean을 생성해야 할땐 특정 Bean을 생성하는 메소드를 직접 호출, 메소드의 파라미터, 또는 클래스레벨의 @Autowired로 특정 Bean을 Injection 받을 수 있다.
위의 예제에서 `antPathMatcher``otherHandler`은 다른곳에서 등록된 Bean을 **메소드의 파라미터** 로 주입받고 있다. 이는 **@Autowired** 를 통해서 주입받는 형태로 바꿀 수도 있다.
```java
@Autowired
AntPathMatcher antPathMatcher;
...
@Bean
public DefaultExceptionHandleManager defaultExceptionHandleManager(ExceptionHandler egovHandler) {
DefaultExceptionHandleManager defaultExceptionHandleManager = new DefaultExceptionHandleManager();
defaultExceptionHandleManager.setReqExpMatcher(antPathMatcher);
defaultExceptionHandleManager.setPatterns(new String[] {"**service.impl.*"} );
defaultExceptionHandleManager.setHandlers(new ExceptionHandler[] {egovHandler});
return defaultExceptionHandleManager;
}
```
이는 Bean을 주입 받는 방법이 다양하므로 다양한 형태의 코드로 구현이 가능함을 기억해 두면 좋을 것이다.
앞선 `defaultExceptionHandleManager`가 메소드의 파라미터 형태로 `egovHandler` 을 주입 받았다면 `otherExceptionHandleManager`**Bean을 생성하는 메소드를 직접 호출**하여 `otherHandler`을 주입 받을 수 있는 것을 확인 할 수 있을 것이다.
```java
@Bean
public DefaultExceptionHandleManager otherExceptionHandleManager() {
DefaultExceptionHandleManager defaultExceptionHandleManager = new DefaultExceptionHandleManager();
defaultExceptionHandleManager.setReqExpMatcher(antPathMatcher);
defaultExceptionHandleManager.setPatterns(new String[] {"**service.impl.*"} );
defaultExceptionHandleManager.setHandlers(new ExceptionHandler[] {otherHandler()});
return defaultExceptionHandleManager;
}
```
참조
-----
https://zgundam.tistory.com/ :
https://atoz-develop.tistory.com/entry/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-XML-%EC%84%A4%EC%A0%95-%ED%8C%8C%EC%9D%BC-%EC%9E%91%EC%84%B1-%EB%B0%A9%EB%B2%95-%EC%A0%95%EB%A6%AC

@ -0,0 +1,84 @@
# [참고] Context Hierarchy(확인 필요)
>*Context 란*
> 필요한 정보를 포함하고 있는 설정의 집합 정도로 생각하자
스프링에서 Context의 계층관계는 부모 자식 관계로 표현 할 수 있다.
아래 처럼 Servlet Context 가 Root Context를 참조한다고 생각하면 되겠다.
![Context Hierarchy](https://docs.spring.io/spring-framework/docs/current/reference/html/images/mvc-context-hierarchy.png)
## Root WebApplicationContext
Middle-tier service, Datasources 등을 포함하고 있다.
View 자원 이외의 공통적으로 이용하는 자원등을 구성할때 주로 사용된다. 우리가 흔히 `@Service`, `@Repository` 등으로 작성하는 영역이 되겠다.
<web.xml>
```xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:egovframework/spring/com/context-*.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
```
ContextLoaderListener를 통해 Root WebApplicationContext를 생성하는데,
`context-param` 엘리먼트를 통해 선언했기 때문에
**Application의 전역**에서 사용 가능한 WebApplicationContext가 되는 것이다.
## Servlet WebbApplicationContext
Controller, view resolvers등 Web과 관련된 빈들이 모두 여기에 해당한다.
주로 Servlet에서 사용하는 View 자원을 구성할때 사용. 우리가 흔히 `@Controller` 로 작성하는 영역이다.
<web.xml>
```xml
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/egovframework/springmvc/*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
```
DispatcherServlet을 통해 Servlet WebApplicationContext를 생성하는데,
`servlet` 엘리먼트를 통해 선언했기 때문에
**해당 Servlet**에서만 사용 가능한 WebApplicationContext가 되는 것이다.
## 계층 관계 컨텍스트
위의 두 context 모두 `param-name``contextConfigLocation` 이라는 것을 볼 수 있다.
이 부분이 Context 간 계층 관계를 연결해주는 부분이다.(?????????)
참조
-----
https://jayviii.tistory.com/9
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#spring-web

@ -0,0 +1,17 @@
# JavaConfig 변환
## 1. XML -> Java Code 변환
### 1) Web.xml 변환
[Context의 계층 관계](./ContextHierarchy.md)
[WebApplicationInitial이란](./WebApplicationInitializer.md)
[WebApplicationInitial 변환](./WebApplicationInitializer_convert.md)
### 2) context-*.xml 변환
## 2. Properties 변환

@ -0,0 +1,99 @@
# Servlet
> **Servlet 이란**
>
> 클라이언트의 요청을 처리하고, 그 결과를 반환하는
> Servlet 클래스의 구현 규칙을 지킨 자바 웹 프로그래밍 기술
자바를 사용하여 웹을 만들기 위해 필요한 기술. 클라이언트가 어떠한 요청을 하면 그에 대한 결과를 다시 전송하기 위한 프로그램. 자바로 구현된 CGI .
> **CGI(Common Gateway Interface)란?**
>
> 웹 서버와 프로그램간의 교환방식. (특별한 라이브러리나 도구를 의미하는 것 X)
> 어떠한 프로그래밍언어로도 구현이가능.
> 클라이언트의 HTTP요청에 대해 특정 기능을 수행하고, HTML 문서등 프로그램의 표준 출력 결과를 클라이언트에게 전송하는 것입니다.
> 즉, 자바 어플리케이션 코딩을 하듯 웹 브라우저용 출력 화면을 만드는 방법입니다.
## Servlet Container 역할
> **Servlet Container**
>
> Servlet을 관리해주는 Container.
>
> 서버에 Servlet을 만들었다고 해서 스스로 작동하는 것이 아님. Servlet의 동작을 관리해주는 역할을 하는 것이 바로 Servlet Container. Servlet Container는 클라이언트의 요청(Request)을 받아주고 응답(Response)할 수 있게, 웹서버와 소켓으로 통신.
>
> ex) 톰캣(Tomcat)
>
> 톰캣은 실제로 웹 서버와 통신하여 JSP와 Servlet이 작동하는 환경을 제공해줍니다.
### 웹 서버와의 통신 지원
일반적인 통신은 소켓을 만들고, 특정 port를 Listening 하고, 연결 요청이 들어오면 스트림을 생성해서 요청을 받는다. Servlet Container는 이런 통신 과정을 API 로 제공하고 있기 때문에 우리가 쉽게 사용할 수 있다.
### 생명주기(Life Cycle) 관리
Servlet Container가 기동 시 Servlet Class를 로딩해서 인스턴스화하고, 초기화 메서드를 호출.
요청이 들어오면 적절한 Servlet 메소드를 찾아서 호출한다.
만약 서블릿의 생명이 다하는 순간 가비지 컬렉션을 진행한다.
### 멀티스레드 지원 및 관리
Servlet Container는 해당 Servlet의 요청이 들어오면 스레드를 생성해서 작업을 수행한다. 즉 동시의 여러 요청이 들어온다면 멀티스레딩 환경으로 동시다발적인 작업을 관리한다.
### 선언적 보안관리
Servlet Container는 보안 관련된 기능을 지원한다. 따라서 서블릿 코드 안에 보안 관련된 메소드를 구현하지 않아도 된다.
## Servlet 동작 방식
1. client가 URL을 입력하면 HTTP Request가 Servlet Container로 전송합니다.![img](https://miro.medium.com/max/711/1*p3bdLuk7wjHFS0n8YJXQ_A.png)
2. 요청을 전송받은 Servlet Container는 HttpServletRequest, HttpServletResponse 객체를 생성합니다.
![img](https://miro.medium.com/max/821/1*Q4tv8s-_NYuHuE3tYbWcfg.png)
3. web.xml을 기반으로 사용자가 요청한 URL이 어느 Servlet에 대한 요청인지 찾습니다.
4. 해당 Servlet에서 service메소드를 호출한 후 클리아언트의 HTTP 프로토콜에 따라 해당 메소를 호출합니다.
![img](https://miro.medium.com/max/761/1*RoDdyWhZxiZ5ODWoK9XnGw.png)
5. 해당 메소드는 동적 페이지를 생성한 후 HttpServletResponse객체에 응답을 보냅니다.
6. 응답이 끝나면 HttpServletRequest, HttpServletResponse 두 객체를 소멸시킵니다.
기존
1. 기존 방식
1) Servlet Container가 먼저 뜨고
2) ServletContainer 안에 등록되는 Servlet Application에다가 Spring을 연동하는 방식이다.
ContextLoaderListener 등록 OR DispatcherServlet 등록
2. boot 방식
1) Spring Boot Application 이 Java Application으로 먼저 뜨고,
2) 그 안에 tomcat이 내장 서버로 뜬다.
3) Servlet(ex, DispatcherServlet)을 내장 톰켓 안에다가 코드로 등록한다.
출처
------
https://mangkyu.tistory.com/14 [MangKyu's Diary]
https://jsonsang2.tistory.com/52 [리루]
https://codeburst.io/understanding-java-servlet-architecture-b74f5ea64bf4
https://jusungpark.tistory.com/15 [정리정리정리]

@ -0,0 +1,135 @@
# [참고] 순수 자바 클래스를 이용한 시동이 가능한 이유
## WebApplicationInitializer
서블릿은 3.0 이후부터 `web.xml` 없이도 서블릿 컨텍스트를 구현 가능하게 합니다.
>**서블릿 컨텍스트 초기화**
>서블릿 등록과 매핑, 리스너 등록, 필터 등록 을 담당한다.
## 스프링 프레임워크의 시동
스프링 프레임워크의 시동 방법 중 순수 자바 클래스만을 이용하여 시동 할 수 있는 방법은 아래와 같다.
1. `javax.servlet.ServletContainerInitializer` 인터페이스를 구현한 클래스 만들고
2. 구현체의 클래스 이름을 `/META-INF/services/javax.servlet.ServletContainerInitializer` 에 준다.
3. 이 구현 클래스에 WAS 시작 시 실행 될 클래스를 `@HandlesTypes` 어노테이션으로 달아준다.
스프링의 경우 이를 spring-web 모듈 내에서 확인 가능하다.
```tex
#/META-INF/services/javax.servlet.ServletContainerInitializer
javax.servlet.ServletContainerInitializer
```
```java
package org.springframework.web;
...
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
List<WebApplicationInitializer> initializers = new inkedList<WebApplicationInitializer>();
...
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
```
`SpringServletContainerInitializer` 클래스는 `@HandlesTypes` 통해 `WebApplicationInitializer.class` 를 지정하고 있다. 이때 `onStartUp()` 메소드의 인자로, 지정된 클래스 set과 서블릿 컨텍스트 객체를 파라미터로 넣어준다.
WAS가 시작될 때 `org.springframework.web.WebApplicationInitializer` 인터페이스를 구현한 각 클래스들의 `onStartup()` 메소드가 실행되어 초기화 작업이 진행된다.
이 인터페이스를 구현한 클래스를 만들어두면 웹 어플리케이션이 시작할 때 자동으로 `onStartup()` 메서드가 실행된다.
## `AnnotationConfigWebApplicationContext` 설정
Spring 3.1 부터는 `WebApplicationInitializer` 사용 시 직접 초기화 하고 `DispatcherServlet`이나 `ContextLoaderListener` 를 직접 주입 할 수 있다.
```java
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
public class EgovWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(ContextApp.class);
servletContext.addListener(new ContextLoaderListener(rootContext));
}
}
```
## Context 설정
### `@Configuration``@Bean`
설정에 관련된 클래스는 클래스 상단에 `@Configuration` 을 달아주면 된다.
Bean의 생성은 메소드를 통해 생성되며 메소드에 @Bean 을 달아주면 된다.
```java
import org.springframework.context.annotation.Configuration;
@Configuration
public class ContextApp {
@Bean
public BeanClass beanName(){
return new BeanClass();
}
}
```
### Context 설정의 모듈화
스프링 XML 파일에서 설정 모듈화에 <import/> 요소를 사용하지만 `@Import` 은 다른 설정 클래스에서 @Bean 설정을 로딩한다. 만약 필요한 XML을 불러와야 하는 상황이면 `@ImportResource`을 통해 불러 올 수 있다.
```java
import org.springframework.context.annotation.Configuration;
@Configuration
@Import({ContextAppCommon.class, ContextAppDatasource.class})
@ImportResource("classpath*:egovframework/spring/com/context-*.xml")
public class ContextApp {
}
```
참고
-------
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.html
https://joont92.github.io/spring/WebApplicationInitializer/
https://offbyone.tistory.com/215
https://blog.outsider.ne.kr/785

@ -0,0 +1,174 @@
# WebApplicationInitializer 변환
## Root WebApplication 등록
### 리스너 등록
> **리스너의 역할**
> Listener는 Servlet Context가 생성하는 이벤트를 전달받는 역할을 한다.
> Servlet Context가 생성하는 이벤트는 컨텍스트 초기화 이벤트와 종료 이벤트이다.
> 즉 웹 어플리케이션이 시작과 종료 시점에 이벤트가 발생하고, 리스너를 등록해두면 이를 받을 수 있는 것이다.
<web.xml>
```xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
```
<EgovWebApplicationInitializer.class>
```java
ServletContextListener listener = new ContextLoaderListener();
servletContext.addListener(listener);
```
여기서 한가지 궁금한 점이 생길 수 도 있을 것이다.
`WebApplicationInitializer``onStartup()`은 Servlet Context 초기화 시점에 실행되는데 굳이 리스너를 등록 해야 하나 생각 할 수 있다.
앞서 리스너는 Servlet Context가 생성하는 이벤트를 전달받는다고 했다. `onStartup()`은 초기화 시점은 정해졌지만, 종료 시점은 캐치할 수 없으므로 리스너를 등록해 놓은 것이다.
### 설정파일 위치 변경
<web.xml>
```xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:egovframework/spring/com/context-*.xml
</param-value>
</context-param>
```
<EgovWebApplicationInitializer.class>
```java
servletContext.setInitParameter("contextConfigLoaction", "classpath*:egovframework/spring/com/context-*.xml");
```
이때 기본 Root WebApplication의 contextClass는 [`XmlWebApplicationContext`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/context/support/XmlWebApplicationContext.html)이고 기본 설정 파일 위치인 `contextConfigLoaction``/WEB-INF/applicationContext.xml` 이다.
### `@Configuration` 사용
`AnnotationConfigWebApplicationContext` 를 이용하면 Java Config 를 이용한 설정으로 사용할 수 있다.
<EgovWebApplicationInitializer.class>
```java
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(ContextApp.class);
ServletContextListener listener = new ContextLoaderListener(rootContext);
servletContext.addListener(listener);
```
`AnnotationConfigApplicationContext``AnnotationConfigWebApplicationContext``AnnotationConfigRegistry`를 구현하고 있으므로 인스턴스화 할때 `@Configuration`클래스들을 input으로 사용 할 수 있다.
> `@Configuration` 클래스들은 `@Component`로 메타 어노테이션이 붙은 클래스라는 것을 기억해라. 그래서 이 클래스들은 컴포넌트 스캔의 후보들이 된다. scan("[스캔하고자 하는 패키지]")을 호출하는 동안 선택될 것이고 클래스의 모든 @Bean 메서드들을 refresh() 할 때 컨테이너내 빈 정의로 처리되고 등록될 것이다.
<ContextApp.java>
```java
@Configuration
@ImportResource(value= {"classpath*:egovframework/spring/com/context-*.xml" })
public class ContextApp {
}
```
기존의 xml 기반 context 설정 파일들은 변경하는 동안 @ImportResource 를 통해 불러오자.
## Servlet Application 등록
Servlet Web Application Context는 Servlet 안에서 초기화 되고 Servlet 이 종료될 때 같이 종료 된다.
이때 사용되는 Servlet 이 DispatcherServlet이다.
기본의 DispatcherServlet 등록은 아래와 같이 작성한다.
### 설정파일 위치 변경
<web.xml>
```xml
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/egovframework/springmvc/*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
```
<EgovWebApplicationInitializer.class>
```java
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("action", new DispatcherServlet());
dispatcher.setInitParameter("contextConfigLocation", "/WEB-INF/config/egovframework/springmvc/*.xml");
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("*.do");
```
### `@Configuration` 사용
`AnnotationConfigWebApplicationContext` 를 이용하면 Java Config 를 이용한 설정으로 사용할 수 있다.
<EgovWebApplicationInitializer.class>
```java
AnnotationConfigWebApplicationContext webApplicationContext = new AnnotationConfigWebApplicationContext();
webApplicationContext.register(ContextWebDispatcherServlet.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(webApplicationContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("*.do");
```
<ContextWebDispatcherServlet.class>
```java
@Configuration
@ImportResource(value= { "/WEB-INF/config/egovframework/springmvc/*.xml" })
public class ContextWebDispatcherServlet {
}
```
출처
---------
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/context/ContextLoader.html
https://blog.outsider.ne.kr/785
https://joont92.github.io/spring/WebApplicationInitializer/

@ -0,0 +1,192 @@
# Aspect 설정
## `@EnableAspectJAutoProxy`
`@EnableAspectJAutoProxy`는 AspectJ 설정을 위해 쓰인다. AspectJ의 자동 프록시 기능이 켜지도록 설정하는 것이고, xml에 `<aop:aspectj-autoproxy/>`를 설정했던 것과 같다.
`<aop:aspectj-autoproxy/>` 는 Spring에서 AOP 구현시 AspectJ 프레임워크 (스타일) 로 구현하도록 설정하는 것이며, 여기서 실제 AspectJ를 사용하는 것이 아닌 AspectJ 스타일을 사용하는 것임을 기억해 두자.
> AspectJ이 구현하는 AOP는 **ByteCode 조작**해 구현
> Spring이 구현하는 AOP는 **Proxy패턴을 이용**해 구현
Spring AspectJ 프레임워크는 AspectJ스타일(문법)을 사용할 뿐 내부적으로는 **Proxy 방식** 을 사용하며 이를 가능하게 해 주는것이 `@EnableAspectJAutoProxy` 이다.
### proxyTargetClass 속성
false 설정 (아무 값도 주지 않을때 ) :
(AOP 대상이 되는 클래스가)
interface를 구현 O => JDK Dynamic Proxy를 만들어서
interface를 구현 X => CGLIB를 이용해서 구현
true 설정 : CG-LIB로만 구현
(AOP 대상이 되는 클래스가)
interface를 구현 O => CGLIB를 이용해서 구현
interface를 구현 X => CGLIB를 이용해서 구현
> CGLIB(Code Generator Library)란
> 런타임에 동적으로 자바 클래스의 프록시를 생성해주는 기능
## Aspect 설정시 알아두면 좋을 것들
### AOP 관련 용어
> **AOP**
>
> 낮은 결합도, 높은 응집도를 위한것.
우리가 작성하는 코드 혹은 프로그램을 **핵심 로직** + **공통 로직(반복적으로 쓰이는 로직, 부가 기능)** 으로 나눠 볼 수 있다.
핵심 로직(비지니스 로직, 서비스 로직)과 공통 관심사(로깅,트랜잭션, security)를 분리하기 위해..
관심을 분리 함으로써 부가적인 공통 관심사를 AOP를 통해 효율적으로 관리, **소스상 결합은 발생하지 않는다.**
#### Separation of Concerns
비지니스 로직을 Core Concerns + Cross-cutting Concerns 로 나눌 수 있다.
#### Core Concerns
업무의 주된 flow.
핵심 비지니스 로직.
#### Cross-cutting Concerns
공통, 반복되는 코드(로직)
로깅, 예외, 트랜잭션 처리 같은 코드들.
#### **Advice**
Cross-cutting Concerns을 구현한 객체. 공통로직을 담은 클래스.
#### JoinPoint (???)
모든 비지니스 메소드. 공통 관심사를 적용할 수 있는 대상이 되는 메소드.
Spring AOP에서는 각 객체의 메소드.
#### **PointCut**
필터링된 JoinPoint. (JoinPoint의 부분집합).
Advice가 어디에 적용될지 결정하는 역할. 다른 여러 메소드중 실제 Advice가 절용될 대상 메소드
#### **Aspect** 또는 Advisor
PointCut과 Advice의 결합. 어떤 PointCut메소드에 어떤 Advice메소드를 실행할지 결정.
#### Target
대상 메소드를 가지는 객체
#### Proxy
Advice가 적용 될 때 만들어 지는 객체
#### Introducing
target에 없는 새로운 메소드나 인스턴스 변수를 추가하는 기능
#### Weaving
Advice와 Target이 결합되어서 Proxy를 만드는 과정
``` ```
```<aop:config>```
스프링 설정 내 여러번 사용 가능
```
<beans xmlns="http://www.springframework.org/schema/beans" ...>
<aop:config>
<aop:pointcut />
</aop:aspect …></aop:aspect>
</aop:config>
</beans>
```
```<aop:pointcut>```
PointCut 을 지정하기 위해 사용.
```<aop:config>``` 나 ```<aop:aspect>``` 의 자식 엘리멘트로 사용
```<aop:aspect>```하위에 설정된 포인트컷은 해당 ```<aop:aspect>```하위에서만 사용 가능
여러개 정의 가능.
```<aop:aspect>```
해당 관심에 해당하는 PointCut 메소드와 횡단 관심에 해당하는 Advice 메소드를 결합하기위해 사용
설정에 따라 Weaving결과가 달라지므로 AOP에서 가장 중요한 설정
```<aop:advisor>```
aspect와 같은 기능
트랜잭션 설정 같은 특수한 경우는 advisor를 사용.
AOP에서 aspect 사용시 advice의 아이디와 메소드 이름을 알아야 하지만 이를 모를때는 사용할 수 없다.
이럴때 advisor를 사용한다.
스프링 컨테이너는 ```<tx:advice>```엘리먼트를 해석하여 트랜잭션 관리 기능의 advice를 생성한다.
txAdvice 설정에 따라 동작이 달라진다.
문제는 advice 아이디는 확인되지만 메소드 이름은 확인 할 방법이 없다.
advice의 동작 시점
* Before : 비지니스 메소드 실행 전 동작 ; <aop:before>
* After
* After Returning : 비지니스 메소드가 성공적으로 리턴되면 동작 ; <aop:after-returning>
* After Throwing : 비지니스 메소드 실행 중 예외가 발생하면 동작(try~catch 블록에서 catch 블록에 해당) ; <aop:after-throwing>
* After : 실행 된 후 무조건 실행(try~catch~finally 블록에서 finally 블록에 해당) ; <aop:after>
* Around : 비지니스 메소드 실행 전후에 처리할 로직을 삽입할 수 있음 <aop::after-around>
``` ```
``` ```
``` ```
``` ```
``` ```
``` ```
*PointCut*
표현식 :
excution :
whitin :
예제 :
<aop:after-throwing throwing="exception" pointcut-ref="serviceMethod" method="transfer" />
참조
----
https://www.hanumoka.net/2018/09/01/spring-20180901-spring-AOP-summary/
https://icarus8050.tistory.com/8
http://closer27.github.io/backend/2017/08/03/spring-aop/
선언적 Transaction : https://freehoon.tistory.com/110
Spring AOP config 변환 : https://m.blog.naver.com/PostView.nhn?blogId=zzxx4949&logNo=221697782544&proxyReferer=https:%2F%2Fwww.google.com%2F
https://dymn.tistory.com/49
https://moonsiri.tistory.com/53
* tx변환 : https://linked2ev.github.io/gitlog/2019/10/02/springboot-mvc-15-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-MVC-Transaction-%EC%84%A4%EC%A0%95/

@ -0,0 +1,112 @@
# Conext-aspect 변환
> AOP 관련 설정을 하는 곳이다.
>
> Exception의 처리를 Exception Handler를 AOP를 통해서 처리하고 있다.
각각의 Exception Handler에 대해서 Java Config로 변경은 쉽다.
<conext-aspect.xml>
```xml
<bean id="egovHandler" class="egovframework.com.cmm.EgovComExcepHndlr" />
<bean id="otherHandler" class="egovframework.com.cmm.EgovComOthersExcepHndlr" />
```
<ContextAppAspect.class>
```java
@Bean
public EgovComExcepHndlr egovHandler() {
EgovComExcepHndlr egovComExcepHndlr = new EgovComExcepHndlr();
return egovComExcepHndlr;
}
@Bean
public EgovComOthersExcepHndlr otherHandler() {
EgovComOthersExcepHndlr egovComOthersExcepHndlr = new EgovComOthersExcepHndlr();
return egovComOthersExcepHndlr;
}
```
각각의 `ExceptionHandleManager` 설정을 진행한다. `defaultExceptionHandleManager`, `otherExceptionHandleManager`설정을 통해 복수개의 Handler를 등록 할 수 있음을 보여준다.
<conext-aspect.xml>
```xml
<bean id="defaultExceptionHandleManager" class="egovframework.rte.fdl.cmmn.exception.manager.DefaultExceptionHandleManager">
<property name="reqExpMatcher">
<ref bean="antPathMater"/>
</property>
<property name="patterns">
<list>
<value>**service.impl.*</value>
</list>
</property>
<property name="handlers">
<list>
<ref bean="egovHandler" />
</list>
</property>
</bean>
```
<ContextAppAspect.class>
```java
@Bean
public DefaultExceptionHandleManager defaultExceptionHandleManager(ExceptionHandler egovHandler) {
DefaultExceptionHandleManager defaultExceptionHandleManager = new DefaultExceptionHandleManager();
defaultExceptionHandleManager.setReqExpMatcher(antPathMatcher);
defaultExceptionHandleManager.setPatterns(new String[] {"**service.impl.*"});
defaultExceptionHandleManager.setHandlers(new ExceptionHandler[] {egovHandler});
return defaultExceptionHandleManager;
}
```
<conext-aspect.xml>
```xml
<bean id="exceptionTransfer" class="egovframework.rte.fdl.cmmn.aspect.ExceptionTransfer">
<property name="exceptionHandlerService">
<list>
<ref bean="defaultExceptionHandleManager" />
<ref bean="otherExceptionHandleManager" />
</list>
</property>
</bean>
```
<ContextAppAspect.class>
```java
@Bean
public ExceptionTransfer exceptionTransfer(
@Qualifier("defaultExceptionHandleManager") DefaultExceptionHandleManager defaultExceptionHandleManager,
@Qualifier("otherExceptionHandleManager") DefaultExceptionHandleManager otherExceptionHandleManager) {
ExceptionTransfer exceptionTransfer = new ExceptionTransfer();
exceptionTransfer.setExceptionHandlerService(new ExceptionHandlerService[] {
defaultExceptionHandleManager, otherExceptionHandleManager
});
return exceptionTransfer;
}
```

@ -0,0 +1,18 @@
# 표준프레임워크 심플홈페이지 템플릿 변환
## 1. [Java Config 변환](./Docs/JavaConfig변환.md)
### 1) Web.xml -> WebApplicationInitializer 구현체로 변환
### 2) context-*.xml -> @Configuration 변환
### 3) properties 변환(예정) boot 지원
## 2. API 변환
직접 View와 연결하던 방법에서 API 형식으로 변환 -> 다양한 프론트에서 적용 가능 하도록 예제 제공
## 3. 프론트 예제
React
Loading…
Cancel
Save