Aspectran Tutorial

본 문서는 Aspectran의 주요 기능에 대한 설명서입니다.

1. 개요

Aspectran은 엔터프라이즈급 자바 웹 응용 프로그램을 구축에 필요한 가장 핵심적인 기능을 제공하는 프레임워크입니다.
구축환경에 따라 달라질 수 있는 부가적인 기능은 직접적으로 제공을 하지 않고, 핵심 기능을 확장 또는 외부 라이브러와 연동을 통해서 부가 기능을 쉽게 추가할 수 있도록 설계되었습니다.

Aspectran 의 주요 기능은 다음과 같습니다.

  • POJO(Plain Old Java Object) 방식의 경량 프레임워크입니다.
    기능 구현을 위해 특정 인터페이스를 구현하거나 상속을 받을 필요가 없습니다. 결과 값은 가장 간단한 자바 오브젝트에 담아서 반환하면 됩니다.
  • 제어 반전(Inversion of Control, IoC)을 지원합니다.
    프레임워크가 전체적인 흐름을 제어하면서 개발자가 작성한 모듈의 기능을 호출하는 방식입니다. 객체에 대한 생성 및 생명주기를 관리할 수 있는 기능을 제공하며, 개발자는 비즈니스 로직에 집중하여 개발할 수 있게 됩니다.
  • 의존성 주입(Dependency Injection, DI)을 지원합니다.
    프레임워크가 실행시에 서로 의존하는 모듈을 연결합니다. 모듈 간의 낮은 결합도를 유지할 수 있고, 코드 재사용성을 높일 수 있습니다.
  • 관점 지향 프로그래밍(Aspect-Oriented Programming, AOP)을 지원합니다.
    핵심 기능과 부가적인 기능을 분리해서 코드를 작성할 수 있습니다. 핵심 기능이 구현된 이후에 트랜잭션이나 로깅, 보안, 예외처리와 관련된 기능을 핵심 기능과 결합할 수 있습니다.
  • RESTful 웹서비스 구축 환경을 지원합니다.

본 문서는 Aspectran의 주요 기능에 대한 설명서입니다.


2. 시작

2.1 설치

Aspectran은 라이브러리 의존성 문제를 최소화 하기 위해 최소한의 외부 라이브러리를 사용합니다. Aspectran을 사용하려면 aspectran-x.x.x.jar 파일과 아래와 같은 필수 의존 라이브러리를 필요로 합니다.

  • javassist or cglib
  • commons-fileupload
  • commons-io
  • logging 라이브러리(commons-logging, log4j, slf4j)

현재 Aspectran 홈페이지의 다운로드 페이지에서 수동으로 jar 라이브러리의 복사본을 받을 수 있습니다.

Maven을 사용한다면 pom.xml 파일을 참고해서 의존 라이브러리를 추가해 주세요.

2.2 작동 환경

Aspectran을 사용해서 Java 웹 어플리케이션을 개발하기 위해서는 다음 요건을 충족해야 합니다.

  • Java 6 이상
  • Servlet 2.5 이상

2.3 웹 컨테이너에 서블릿으로 등록하기

Aspectran Configuration에 필요한 초기화 파라메터 aspectran:config를 정의하고, AspectranServiceListener를 등록해서 ActivityContext를 생성하도록 합니다.

요청 URI가 /example/이면 WebActivityServlet라는 서블릿이 처리하도록 했습니다. 스케쥴러를 사용할 경우 개발환경에서 Job을 직접 실행해 볼 수 있도록 /scheduler/로 시작하는 URL도 맵핑했습니다.

만약 WebActivityServlet라는 서블릿이 처리하지 못하는 요청은 DefaultServlet으로 처리권을 넘겨줍니다. DefaultServlet의 이름은 명시적으로 지정하지 않았지만, 내부적으로 웹어플리케이션 서버 종류에 따라서 자동으로 판단합니다. 잘 알려진 웹어플리케이션 서버가 아닐 경우 DefaultServlet의 이름을 수동으로 명시할 수도 있습니다.

web.xml

<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
  <display-name>aspectran-examples</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <context-param>
    <param-name>aspectran:config</param-name>
    <param-value>
      context: {
        root: "/WEB-INF/aspectran/config/getting-started.xml"
        encoding: "utf-8"
        resources: [
          "/WEB-INF/aspectran/config"
          "/WEB-INF/aspectran/classes"
          "/WEB-INF/aspectran/lib"
        ]
        hybridLoad: false
        autoReload: {
          reloadMethod: hard
          observationInterval: 5
          startup: true
        }
      }
      scheduler: {
        startDelaySeconds: 10
        waitOnShutdown: true
        startup: false
      }
    </param-value>
  </context-param>
  <listener>
    <listener-class>com.aspectran.web.startup.listener.AspectranServiceListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>aspectran-example</servlet-name>
    <servlet-class>com.aspectran.web.startup.servlet.WebActivityServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>aspectran-example</servlet-name>
    <url-pattern>/example/*</url-pattern>
  </servlet-mapping>
  <!-- 실제 운영환경에서는 스케쥴러의 Job에 직접 접근할 수 없도록 서블릿매핑을 제거하도록 합니다. -->
  <servlet-mapping>
    <servlet-name>aspectran-example</servlet-name>
    <url-pattern>/scheduler/*</url-pattern>
  </servlet-mapping>
</web-app>

2.3.1 초기화 파라메터 정의

먼저 컨텍스트 초기화 파라메터 aspectran:config를 정의합니다. aspectran:config 파라메터는 APON(Aspectran Parameter Object Notation) 문서형식의 설정 값을 가질 수 있습니다.

APON(Aspectran Parameter Object Notation)은 JSON 과 표기법이 비슷합니다. 미리 정해진 형식의 파라메터를 주고 받기 위해서 새롭게 개발된 표기법입니다.

context
Aspectran 환경설정을 위한 정의
context.root
환경 설정을 위해 가장 먼저 참조할 xml 파일의 경로
context.encoding
XML 파일을 APON 문서형식으로 변환시에 문자열 인코딩 방식을 지정
context.resources
Aspectran에서 별도로 관리할 수 있는 리소스의 경로를 배열로 지정
(Aspectran은 계층형의 ClassLoader를 별도로 내장하고 있습니다.)
다음과 리소스 경로를 지정할 수 있습니다.
/WEB-INF/aspectran/config
/WEB-INF/aspectran/classes
/WEB-INF/aspectran/lib
file:/c:/Users//Projects/java/classes
context.hybridLoad
환경 설정을 빠르게 로딩하기 위해 다수의 XML 파일을 APON 문서형식으로 변환할지 여부를 지정합니다. XML 형식의 환경 설정 파일이 수정되면 APON 파일로 변환되고, 다음 기동 시에 XML 파일을 로딩하는 것이 아니라 APON 파일을 찾아서 로딩합니다. 다수의 XML 파일을 파싱하는 걸리는 시간을 단축할 수 있습니다.
context.autoReload
리소스 자동 갱신 기능에 대한 정의 (Aspectran에서 별도로 관리하는 리소스에 대해서는 WAS를 재시작을 하지 않더라도 자동 갱신이 가능합니다.)
context.autoReload.reloadMethod
리소스의 갱신 방법을 지정 (hard: Java Class 갱신 가능 , soft: 환경 설정 내역만 갱신 가능)
context.autoReload.observationInterval
리소스가 수정 여부를 관찰하는 시간 간격을 초 단위로 지정
context.autoReload.startup
리소스 자동 갱신 기능을 사용할지 여부를 지정
scheduler
스케쥴러 동작환경을 위한 정의
scheduler.startDelaySeconds
모든 환경이 초기화된 후 스케쥴러가 기동 지연 시간을 초 단위로 지정
scheduler.waitOnShutdown
실행중인 모든 Job이 종료되기를 기다렸다가 스케쥴러를 종료할지 여부를 지정
scheduler.startup
스케쥴러를 기동할지 여부를 지정

각 초기화 파라메터 별로 기본 값은 다음과 같습니다.

파라메터기본 값
context 
context.root/WEB-INF/aspectran/root.xml
context.encoding 
context.resources 
context.hybridLoadfalse
context.autoReloadfalse
context.autoReload.reloadMethodsoft
context.autoReload.observationInterval10
context.autoReload.startupfalse
scheduler 
scheduler.startDelaySeconds5
scheduler.waitOnShutdownfalse
scheduler.startupfalse

2.3.2 AspectranServiceListener 등록

<listner-class>com.aspectran.web.startup.listener.AspectranServiceListener를 지정합니다. AspectranServiceListener는 컨텍스트 초기화 파라메터 aspectran:config의 설정 내용으로 Aspectran 서비스 환경을 구성하고, Application Scope를 가지고 있습니다.

AspectranServiceListener에 의해 기동된 Aspectran 서비스는 여러 WebActivityServlet에서 사용될 수 있습니다. 즉, 전역적인 하나의 Aspectran 서비스 환경을 구성할 수 있습니다.

2.3.3 WebActivityServlet 등록

<servlet-class>com.aspectran.web.startup.servlet.WebActivityServlet을 지정합니다. <servlet-name>에는 Aspectran 서비스를 위한 서블릿이라는 의미의 고유한 서블릿 이름을 부여해 주기 바랍니다.

서블릿 초기화 파라메터로 aspectran:cofnig를 정의하면 서블릿만의 단독 Aspectran 서비스 환경을 구성합니다. 즉, 전역 Aspectran 서비스를 사용하지 않습니다.

2.3.4 서블릿 URL 패턴 등록

<url-pattern>에 해당하는 요청은 WebActivityServlet이 처리할 수 있도록 합니다. 만약 <url-pattern>/example/*로 지정하면 /example/로 시작하는 이름을 가진 Translet이 실행됩니다.

Aspectran의 Translet이란? 요청을 받고 결과 값을 적절히 가공해서 응답하는 처리자를 Aspectran 내부에서는 Translet이라고 명명하였습니다. Translet은 고유 이름을 가지고 있으며, 요청 URI와 직접적으로 매핑이 됩니다. 스케쥴러의 Job도 Translet을 통해서 실행이 됩니다.

2.3.5 DefaultServlet 이름 지정하기

요청 URI에 해당하는 Translet이 존재하지 않을 경우 서블릿 컨테이너의 DefaultServlet에게 넘겨주는 역할을 하는 핸들러가 항상 동작하고 있습니다. 그 핸들러의 이름은 DefaultServletHttpRequestHandler입니다. DefaultServletHttpRequestHandler는 DefaultServlet의 이름이 무엇인지 자동으로 판단합니다. 만약 DefaultServlet의 이름이 다르게 지정되어야 할 경우 아래와 같은 초기화 파라메터를 추가합니다.

<context-param>
    <param-name>aspectran:defaultServletName</param-name>
    <param-value>default</param-value>
</context-param>

3. Aspectran Configuration

Aspectran이 구동되기 위해서는 구조화된 설정 메타데이터를 필요로 합니다.
설정 메타데이터는 전통적인 XML 형식 또는 APON 형식의 파일로 작성해야 하며, 계층적으로 모듈화되어 여러 개의 파일로 나눌 수도 있습니다.

Aspectran은 설정 메타데이터를 자바 소스코드와 완전히 분리하는 것을 기본 원칙으로 합니다.
어플리케이션 개발자가 작성하는 자바 소스코드는 POJO 형태를 최대한 유지할 수 있습니다.
또한, 설정 메타데이터 구성에 필요한 요소는 오래 시간에 걸쳐서 최적화가 되었기 때문에 최소한의 구성요소를 가지고도 다양한 설정이 가능합니다.

설정 메타데이터를 구성하는 대표적인 구성요소는 다음과 같습니다.

settings
기본 설정항목을 정의합니다.
하위 설정 파일은 상위 설정 파일의 기본 설정 값을 물려 받습니다.
aspect
Bean과 Translet이 가진 원래의 기능에 다른 부가 기능을 주입하는 방법을 정의합니다.
관점지향프로그래밍(AOP)을 지원하기 위한 핵심 요소입니다.
bean
IoC, DI의 대상이 되고, 기능을 가진 객체를 정의합니다.
객체를 인스턴스화 하는 방법, 객체의 생명주기, 객체의 속성 값, 객체의 의존관계를 설정할 수 있습니다.
translet
요청 URI와 맵핑되어 비지니스 로직을 가지고 있는 Action Method를 호출하는 방법 및 응답 컨텐츠를 출력하는 방법을 정의합니다.
import
다른 설정 파일을 불러오는 방법을 정의합니다.

다음 예제는 XML 기반의 설정 메타데이터의 기본 구조를 보여주기 위해 작성되었습니다.

getting-started.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE aspectran PUBLIC "-//aspectran.com//DTD Aspectran 1.0//EN"
                           "http://aspectran.github.io/dtd/aspectran-1.0.dtd">

<aspectran>

  <description>
    Aspectran Tutorial 작성을 위한 Aspectran Configuration입니다.
  </description>

  <!-- 기본 설정 -->
  <settings>
    <setting name="transletNamePattern" value="/example/*"/>
  </settings>

  <bean id="*" mask="com.aspectran.example.**.*" class="com.aspectran.example.**.*Action" scope="singleton">
    <description>
      com.aspectran.eaxmple 패키지 하위의 모든 경로에서 클래스 이름이 "Action"으로 끝나는 클래스를
      모두 찾아서 Bean으로 등록합니다.
      만약 com.aspectran.example.sample.SampleAction 클래스가 검색되었다면
      Mask 패턴 "com.aspectran.example.**.*"에 의해 최종적으로 Bean ID는 "sample.SampleAction"이 됩니다.
    </description>
    <filter>
      exclude: [
        "com.aspectran.example.common.**.*"
        "com.aspectran.example.sample.**.*"
      ]
    </filter>
  </bean>

  <bean id="advice.*" mask="com.aspectran.example.**.*" class="com.aspectran.example.**.*Advice" scope="singleton">
    <description>
      com.aspectran.eaxmple 패키지 하위의 모든 경로에서 클래스 이름이 "Advice"으로 끝나는 클래스를
      모두 찾아서 ID가 "advice."으로 시작하는 Bean으로 등록합니다.
      만약 com.aspectran.example.sample.SampleAction 클래스가 검색되었다면
      Mask 패턴 "com.aspectran.example.**.*"에 의해 최종적으로 Bean ID는 "advice.sample.SampleAction"이 됩니다.
    </description>
    <filter class="com.aspectran.example.common.UserClassScanFilter"/>
  </bean>

  <bean id="sampleBean" class="com.aspectran.example.sample.SampleBean" scope="singleton"/>

  <bean id="multipartRequestWrapperResolver" class="com.aspectran.support.http.multipart.MultipartRequestWrapperResolver" scope="singleton">
    <description>
      multipart/form-data request를 처리하기 위해서 반드시 지정해야 합니다.
    </description>
    <property>
      <item name="maxRequestSize" value="10M"/>
      <item name="tempDirectoryPath" value="/d:/temp"/>
      <item name="allowedFileExtensions" value=""/>
      <item name="deniedFileExtensions" value=""/>
    </property>
  </bean>

  <bean id="jspViewDispatcher" class="com.aspectran.web.view.JspViewDispatcher" scope="singleton">
    <description>
      Aspectran의 Translet이 처리한 결과값을 화면에 표현하기 위해 JSP를 이용합니다.
    </description>
    <property>
      <item name="templateFilePrefix">/WEB-INF/jsp/</item>
      <item name="templateFileSuffix">.jsp</item>
    </property>
  </bean>

  <aspect id="defaultRequestRule">
    <description>
      요청 정보를 분석하는 단계에서 사용할 기본 환경 변수를 정의합니다.
      multipart/form-data request를 처리하기 위해 multipartRequestWrapperResolver를 지정합니다.
    </description>
    <joinpoint scope="request"/>
    <settings>
      <setting name="characterEncoding" value="utf-8"/>
      <setting name="multipartRequestWrapperResolver" value="multipartRequestWrapperResolver"/>
    </settings>
  </aspect>

  <aspect id="defaultResponseRule">
    <description>
      요청에 대해 응답하는 단계에서 사용할 기본 환경 변수를 정의합니다.
      기본 viewDispatcher를 지정합니다.
    </description>
    <joinpoint scope="response"/>
    <settings>
      <setting name="characterEncoding" value="utf-8"/>
      <setting name="defaultContentType" value="text/html"/>
      <setting name="viewDispatcher" value="jspViewDispatcher"/>
    </settings>
  </aspect>

  <aspect id="defaultExceptionRule">
    <description>
      Translet의 이름이 "/example"로 시작하는 Translet을 실행하는 중에 발생하는 에러 처리 규칙을 정의합니다.
    </description>
    <joinpoint scope="translet">
      <pointcut>
        target: {
          translet: "/example/*"
        }
      </pointcut>
    </joinpoint>
    <exception>
      <description>
        에러요인과 응답 컨텐츠의 형식에 따라 처리방식을 다르게 정할 수 있습니다.
        exceptionType을 지정하지 않으면 모든 exception에 반응합니다.
      </description>
      <responseByContentType exceptionType="java.lang.reflect.InvocationTargetException">
        <transform type="transform/xml" contentType="text/xml">
          <echo id="result">
            <item type="map">
              <value name="errorCode">E0001</value>
              <value name="message">error occured.</value>
            </item>
          </echo>
        </transform>
        <transform type="transform/json" contentType="application/json">
          <echo id="result">
            <item type="map">
              <value name="errorCode">E0001</value>
              <value name="message">error occured.</value>
            </item>
          </echo>
        </transform>
      </responseByContentType>
    </exception>
  </aspect>

  <aspect id="helloWorldAdvice">
    <description>
      요청 URI가 "/example/"로 시작하고,
      helloworld.HelloWorldAction 빈에서 echo, helloWorld, counting 메쏘드 호출 전 후로
      환영인사와 작별인사를 건넵니다.
    </description>
    <joinpoint scope="translet">
      <pointcut>
        target: {
          +: "/example/**/*@helloworld.HelloWorldAction^echo|helloWorld|counting"
        }
      </pointcut>
    </joinpoint>
    <advice bean="advice.helloworld.HelloWorldAdvice">
      <before>
        <action method="welcome"/>
      </before>
      <after>
        <action method="goodbye"/>
      </after>
    </advice>
  </aspect>

  <aspect id="checkCountRangeAdvice">
    <description>
      요청 URI가 "/example/counting"이고,
      요청 헤더 분석을 완료한 시점에 advice.helloworld.HelloWorldAdvice 빈의 checkCountRange 메쏘드가 실행됩니다.
      checkCountRange 메쏘드는 카운팅할 숫자의 범위가 적합한지 검사합니다.
      만약 적합하지 않을 경우 안전한 값으로 변경합니다.
    </description>
    <joinpoint scope="request">
      <pointcut>
        target: {
          +: "/example/counting"
        }
      </pointcut>
    </joinpoint>
    <advice bean="advice.helloworld.HelloWorldAdvice">
      <after>
        <action method="checkCountRange"/>
      </after>
    </advice>
  </aspect>

  <translet name="echo">
    <description>
      "Hello, World."라는 문구를 텍스트 형식의 컨텐츠로 응답합니다.
      특정 Action을 실행하지 않아도 간단한 텍스트 기반의 컨텐츠를 생산할 수 있습니다.
    </description>
    <transform type="transform/text" contentType="text/plain">
      <template>
        Hello, World.
      </template>
    </transform>
  </translet>

  <translet name="helloWorld">
    <description>
      helloworld.HelloWorldAction 빈에서 helloWorld 메쏘드를 실행해서 "Hello, World."라는
      문구를 텍스트 형식의 컨텐츠로 응답합니다.
    </description>
    <transform type="transform/text" contentType="text/plain">
      <action bean="helloworld.HelloWorldAction" method="helloWorld"/>
    </transform>
  </translet>

  <translet name="counting">
    <description>
      시작 값과 마지막 값을 파라메터로 받아서 숫자를 출력하는 Translet입니다.
      request 영역의 attribute가 생성된 후에 숫자의 범위가 유효한지를 검사하는
      checkCountRangeAdvice Aspect가 작동됩니다.
    </description>
    <request>
      <attribute>
        <item name="from"/>
        <item name="to"/>
      </attribute>
    </request>
    <content>
      <action id="count1" bean="helloworld.HelloWorldAction" method="counting">
        <arguments>
          <item valueType="int">@{from}</item>
          <item valueType="int">@{to}</item>
        </arguments>
      </action>
    </content>
    <response>
      <transform type="transform/xml"/>
    </response>
  </translet>

  <translet name="*" path="/WEB-INF/jsp/**/*.jsp">
    <description>
      '/WEB-INF/jsp/' 디렉토리 하위 경로에서 모든 JSP 파일을 찾아서 Translet 등록을 자동으로 합니다.
      viewDispatcher는 defaultResponseRule Aspect에서 지정한 jspViewDispatcher를 사용합니다.
      검색된 jsp 파일의 경로는 template 요소의 file 속성 값으로 지정됩니다.
    </description>
    <dispatch>
      <template/>
    </dispatch>
  </translet>

  <!-- RESTful 방식의 Translet을 불러들입니다. -->
  <import file="/WEB-INF/aspectran/config/restful-translets.xml"/>

  <!-- 스케쥴러 환경설정을 불러들입니다. -->
  <import file="/WEB-INF/aspectran/config/example-scheduler.xml"/>

</aspectran>

3.1 기본 설정

settings 엘리먼트는 다음과 같은 Aspectran의 기본 설정 항목을 가질 수 있습니다.

transletNamePattern
Translet 이름의 패턴. Translet 이름 문자열은 <servlet-mapping><url-pattern>의 값으로 시작해야 접근이 가능합니다.
transletNamePrefix
transletNamePattern 대신 prefix와 suffix를 지정할 수 있습니다.
transletNameSuffix
transletNamePattern 대신 prefix와 suffix를 지정할 수 있습니다.
transletInterfaceClass
사용자 정의 Translet의 인터페이스 클래스를 지정합니다.
nullableContentId
<content>의 id 속성을 생략할 수 있는지 여부를 지정합니다.
nullableActionId
<action>의 id 속성을 생략할 수 있는지 여부를 지정합니다.
beanProxifier
자바 바이트코드 생성기(Byte Code Instumentation, BCI) 라이브러리를 지정합니다.
pointcutPatternVerifiable
pointcut 패턴의 유효성을 체크할지 여부를 지정합니다.

기본 설정 항목 별로 사용가능한 값과 기본 값은 다음과 같습니다.

기본 설정 항목사용가능한 값기본 값
transletNamePattern/example/*.do설정하지 않음
transletNamePrefix/example/설정하지 않음
transletNameSuffix.do설정하지 않음
transletInterfaceClasscom.aspectran.example.common.MyTranslet설정하지 않으면 내장 Translet을 사용
transletImplementClasscom.aspectran.example.common.MyTransletImpl설정하지 않으면 내장 Translet을 사용
nullableContentIdtrue, falsetrue
nullableActionIdtrue, falsetrue
beanProxifierjavassist, cglib, jdkjavassist
pointcutPatternVerifiabletrue, falsetrue

기본 설정 항목을 모두 사용한 settings 엘리먼트의 예제입니다.

<settings>
    <setting name="transletNamePattern" value="/example/*"/>
    <setting name="transletInterfaceClass" value="com.aspectran.example.common.MyTranslet"/>
    <setting name="transletImplementClass" value="com.aspectran.example.common.MyTransletImpl"/>
    <setting name="nullableContentId" value="true"/>
    <setting name="nullableActionId" value="true"/>
    <setting name="beanProxifier" value="javassist"/>
    <setting name="pointcutPatternVerifiable" value="true"/>
</settings>

3.2 Bean 정의

특정 기능을 가진 객체를 모두 Bean으로 정의할 수 있습니다. Aspectran은 정의된 Bean을 객체로 생성하고 객체간의 관계 설정, 생명주기 관리등의 기능을 제공합니다.

3.2.1 단일 Bean 정의

중요한 역할을 하는 Bean 또는 별도의 속성을 가지는 Bean은 단독으로 정의합니다.

<!-- Aspectran의 Translet이 처리한 결과값을 화면에 표현하기 위해 JSP를 이용합니다. -->
<bean id="jspViewDispatcher" class="com.aspectran.web.view.JspViewDispatcher" scope="singleton">
  <property>
    <item name="templatePathPrefix">/WEB-INF/jsp/</item>
    <item name="templatePathSuffix">.jsp</item>
  </property>
</bean>
<bean id="*" class="com.aspectran.example.sample.SampleBean" scope="singleton"/>

id 속성값으로 * 문자를 지정하면 클래스명이 Bean ID로 지정됩니다.

3.2.2 일괄 Bean 정의

와일드카드를 사용하면 클래스패스에 존재하는 Bean을 일괄 검색해서 한꺼번에 정의할 수 있습니다.

class 속성 값에 사용할 수 있는 와일드카드 문자들은 *, ?, + 이고, Escape 문자로 \ 문자를 사용할 수 있습니다. 여러 패키지를 포함할 경우 .**. 문자를 중간에 사용하면 되는데, 예를들어 com.**.service.*.*Action과 같이 사용할 수 있습니다.

<beans id="*" class="com.aspectran.example.**.*" class="com.aspectran.example.**.*Action" scope="singleton"/>

위 예제에 대한 설명입니다.
com.aspectran.eaxmple 패키지 하위의 모든 경로에서 클래스 이름이 “Action”으로 끝나는 클래스를 모두 찾아서 Bean으로 등록합니다. 만약 com.aspectran.example.sample.SampleAction 클래스가 검색되었다면 Mask 패턴 com.aspectran.example.**.*에 의해 최종적으로 Bean의 ID는 sample.SampleAction이 됩니다.
Mask 패턴에 해당하는 문자열은 제거가 됩니다.

filter 엘리멘트를 이용해서 일괄 검색에서 제외할 클래스를 지정할 수 있습니다.

<bean id="advice.*" mask="com.aspectran.example.**.*" class="com.aspectran.example.**.*Advice" scope="singleton">
	<filter>
		exclude: [
			"com.aspectran.example.common.**.*"
			"com.aspectran.example.sample.**.*"
		]
	</filter>
</bean>

위 예제에 대한 설명입니다.
com.aspectran.eaxmple 패키지 하위의 모든 경로에서 클래스 이름이 “Advice”으로 끝나는 클래스를 모두 찾아서 ID가 advice.으로 시작하는 Bean으로 등록합니다. 만약 com.aspectran.example.sample.SampleAction 클래스가 검색되었다면 Mask 패턴 com.aspectran.example.**.*에 의해 최종적으로 Bean의 ID는 advice.sample.SampleAction이 됩니다. filter 엘리멘트의 exclude 파라메터는 배열로 두 개의 제외 패턴 문자열 값을 가지고 있습니다. 제외 패턴에 해당하는 클래스는 검색 결과에서 제외됩니다.

사용자 정의 필터 클래스를 지정할 수 있습니다.
com.aspectran.core.context.bean.scan.BeanClassScanFilter 인터페이스를 구현해야 합니다.

<bean id="advice.*" mask="com.aspectran.example.**.*" class="com.aspectran.example.**.*Advice" scope="singleton">
	<filter class="com.aspectran.example.common.UserClassScanFilter"/>
</bean>

사용자 정의 필터 클래스 작성 예제:

package com.aspectran.example.common;

import com.aspectran.core.context.bean.scan.BeanClassScanFilter;

public class UserClassScanFilter implements BeanClassScanFilter {

	public String filter(String beanId, String resourceName, Class<?> scannedClass) {
		return beanId;
	}

}

3.2.3 Bean ID 부여 규칙

  1. 일차적으로 검색된 클래스명을 Bean의 ID로 사용합니다.
  2. Mask 패턴을 지정하면 Bean ID에서 불필요한 문자열을 제거할 수 있습니다.
  3. id 속성의 값이 *이면 검색된 Bean ID 또는 클래스명을 그대로 사용합니다.
  4. id 속성의 값이 advice.*이면 Bean ID 앞에 advice. 문자열을 붙입니다.
  5. id 속성의 값이 *Action이면 Bean ID 뒤에 Action 문자열을 붙입니다.

예를 들어
id가 advice.*이고,
mask가 com.aspectran.example.**.*이고,
class가 com.aspectran.example.**.*Action이고,
검색된 클래스의 이름이 com.aspectran.example.hellloworld.HelloWorldAction이면
최종적으로 Bean의 ID는
advice.hellloworld.HelloWorldAction 됩니다.

3.2.4 상세한 Bean 정의 방법

3.2.4 상세한 Bean 정의 방법

다음 예제를 기준으로 Bean을 정의하기 위해 사용된 엘리멘트에 대해 설명합니다.

<bean id="sampleBean">
    <features>
        <class>com.aspectran.sample.SampleAction</class>
        <scope>singleton</scope>
        <initMethod>initialize</initMethod>
        <destroyMethod>destory</destroyMethod>
        <lazyInit>true</lazyInit>
    </features>
    <constructor>
        <arguments>
            <item>arg1</item>
            <item type="list" valueType="int">
              <value>1</value>
              <value>2</value>
              <value>3</value>
            </item>
        </arguments>
    </constructor>
    <property>
        <item name="name">david</item>
        <item name="grade" type="list">
            <value>A</value>
            <value>B</value>
        </item>
        <item name="amount" type="map">
            <value name="food" valueType="float">123456</value>
            <value name="transportation expenses" valueType="1234">value</value>
        </item>
        <item name="anotherBean">
            <reference bean="anotherBean"/>
        </item>
    </property>
</bean>
bean
Bean을 정의하기 위한 최상위 엘리멘트입니다. mask 속성 외에 features 엘리멘트의 하위 엘리멘트를 속성으로 가질 수 있습니다.
bean.features
Bean의 기본 스펙을 정의하는 엘리멘트입니다.
bean.features.class
Bean의 클래스명을

3.3 Aspect 정의

Aspectran이 지원하는 AOP(Aspect Oriented Programming)는 다른 프레임웤에 비해 사용법이 쉽습니다. Aspectran의 AOP는 Translet, Bean 영역 내에서의 메쏘드 호출 조인포인트(Joingpoint)를 지원합니다.

Aspect는 다음 용도로 사용될 수 있습니다.

  • 핵심 비지니스 로직과 공통적인 부가 비지니스 로직을 분리해서 코드를 작성할 수 있습니다.

    ex) 로깅, 인증, 권한, 성능 테스트

  • 트랜잭션 처리

    주로 데이터베이스 트랜잭션 기능을 지원하기 사용합니다.

Aspect를 이용해서 환경변수 선언하기

Aspectran은 외부의 접속 요청을 Translet이 받아서 처리합니다. Translet의 내부에는 Request, Contents, Response 라는 세 가지 영역이 있습니다. Translet과 Request, Contents, Response 영역에서 참조할 수 있는 공통 환경변수를 선언할 수 있습니다.

Translet 내부의 세 가지 영역

  • Request: 요청 정보를 분석하는 영역
  • Contents: 액션을 실행하고 결과 값을 생산하는 영역
  • Response: 생산된 결과 값을 출력하는 영역
<!-- 요청 정보를 분석하는 단계에서 사용할 기본 환경 변수를 정의합니다. -->
<aspect id="defaultRequestRule">
	<joinpoint scope="request"/>
	<settings>
		<setting name="characterEncoding" value="utf-8"/>
		<setting name="multipart.maxRequestSize" value="10M"/>
		<setting name="multipart.tempDirectoryPath" value="/d:/"/>
	</settings>
</aspect>

<!-- 요청에 대해 응답하는 단계에서 사용할 기본 환경 변수를 정의합니다. -->
<aspect id="defaultResponseRule">
	<joinpoint scope="response"/>
	<settings>
		<setting name="characterEncoding" value="utf-8"/>
		<setting name="defaultContentType" value="text/html"/>
		<setting name="viewDispatcher" value="jspViewDispatcher"/>
	</settings>
</aspect>

Check out the documentation for all the tricks ›