Doc: Add Documents
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를 참조한다고 생각하면 되겠다.
|
||||
|
||||

|
||||
|
||||
## 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로 전송합니다.
|
||||
|
||||
|
||||
|
||||
2. 요청을 전송받은 Servlet Container는 HttpServletRequest, HttpServletResponse 객체를 생성합니다.
|
||||

|
||||
|
||||
3. web.xml을 기반으로 사용자가 요청한 URL이 어느 Servlet에 대한 요청인지 찾습니다.
|
||||
|
||||
4. 해당 Servlet에서 service메소드를 호출한 후 클리아언트의 HTTP 프로토콜에 따라 해당 메소를 호출합니다.
|
||||

|
||||
|
||||
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…
Reference in New Issue