Spring DI(Dependency Injection)와 AOP(Aspect Oriented Programming) 맛보기
Spring
Spring이란 무엇인가?엔터프라이즈 어플리케이션에서 필요로 하는 기능을 제공하는 프레임 워크이다.
J2EE에서 제공하는 다양한 기능 뿐만 아니라, DI, AOP와 같은 기능도 지원하고 있다.
특징
1. 스프링은 경량 컨테이너 이다.
스프링은 자바 객체를 담고 있는 컨테이너이다. 스프링은 이들 자바 객체의 생성, 소멸과 같은 라이프 사이클을 관리하며, 스프링으로부터 필요한 객체를 가져와 사용할 수 있다.
2. 스프링은 DI패턴을 지원한다.
스프링은 설정 파일을 통해서 객체간의 의존 관계를 설정할 수 있도록 하고 있다. 따라서 객체는 직접 의존하고 있는 객체를 생성하거나 검색할 필요가 없다.
3. 스프링은 AOP를 지원한다.
스프링은 자체적으로 AOP를 지원하고 있기 때문에 트랜잭션이나 로깅 보안과 같이 여러 모듈에서 공통적으로 필요로 하지만 실제 모듈의 핵심이 아닌 기능들을 분리해서 각 모듈에 적용할 수있다.
4. 스프링은 POJO를 지원한다.
스프링 컨테이너에 저장되는 자바 객체는 특정한 인터페이스를 구현하거나, 클래스를 상속받지 않아도 된다. 따라서 기존에 작성한 코드를 수정할 필요없이 스프링에서 사용할 수 있다.
5. 트랜잭션 처리를 위한 일관된 방법을 제공한다.
JDBC를 사용하든, JTA를 사용하든 또는 컨테이너가 제공하는 트랜잭션을 사용하든, 설정 파일을 통해 트랜잭션 관련 정보를 입력하기 때문에, 트랜잭션 구현에 상관없이 동일한 코드를 여러 환경에서 사용할 수 있다.
6. 영속성과 관련된 다양한 API를 제공한다.
스프링은 JDBC를 비롯하여 iBatis, 하이버네이트등 데이터베이스 처리와 관련하여 널리 사용되는 라이브러리와의 연동을 지원하고 있다.
7. 다양한 API에 대한 연동을 지원한다.
스프링은 JMS, 메일, 스케쥴링등 엔터프라이즈 어플리케이션을 개발하는데 필요한 다양한 API를 설정 파일을 통해서 손쉽게 사용할 수 있도록 하고 있다.
8. 자체적으로 MVC프레임워크를 제공한다.
때문에 스프링만 사용하면 MVC기반의 웹어플리케이션을 어렵지 않게 개발할수 있다.
Spring Framework의 설치와 모듈 구성
1. http://Springframework.org/download 에서 최신 버전을 다운 받는다 (현재: 2.5.6)
2. 압축을 푼다
dist폴더 : 스프링 Jar파일을 포함하고 있는 폴더
lib폴더 : 스프링을 사용하는 필요한 모든 외부 라이브러리를 포함하고 있는 폴더
docs폴더 : 스프링 레퍼런스 및 API Javadoc를 포함하고 있는 폴더
DI(Dependency Injection과 Spring Framework)
객체사이의 의존 관계를 객체끼리 직접하는것이 아니라, 외부 조립기가 수행한다는 개념
의존 관계 처리 방법 3가지
1. 코드에 직접 의존 객체 명시 AbstractDAO dao = new LoginDAO();
2. Factory 패턴이나 JNDI등을 사용해 클래스를 명시 (EJB같은곳에서 사용)
AbstractDAO dao = DAOFactory.create();
3. 외부 조립기를 사용 (Dependency Injection - DI 패턴 ~Inversion of Control)
외부 조립기를 사용하는 이 방법은 불필요한 의존 관계를 없애주는 좋은 방법이다.
DI패턴을 이용하면 직접적으로 객체에 의지 하지 않고 인터페이스에만 의존하게 된다.
DI패턴 적용 두가지 방법
1. 생성자 방식을 이용하여 설정
2. 설정 메소드를 이용하여 설정 (setter)
2. 스프링 설정 파일을 이용하여 의존 관계 설정(applicationContext.xml))
<bean name="writeArticleService"
class="kame.spring.chap01.WriteArticleServiceImpl">
<constructor-arg>
<ref bean="articleDao" />
</constructor-arg>
</bean>
<bean name="articleDao"
class="kame.spring.chap01.MysqlArticleDao">
</bean>
의 의미는
MySqlArticleDao articleDao = new MyArticleDao();
WriteArticleServiceImpl writeArticleService = new WriteArticleServiceImpl (articleDao);
위와 같은 xml 선언을 통해 WriteArticleServiceImpl객체와 MySqlArticleDao객체 사이의 의존 관계를 설정하였다.
//이렇게 설정하면 스프링 컨테이너로 부터 빈 객체를 가져와서 사용 할 수 있다.
Resource resource = new ClassPathResource("applicationContext.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
WriteArticleService articleService =
(WriteArticleService) beanFactory.getBean("writeArticleService");
articleService.write(new Article);
이것을 제어 역행이라고 하는데, 스프링 프레임 워크의 핵심이다.
의존성을 띄는 객체를 내가 생성하는 것이 아니라,
내가 주입 받는것이다. 따라서 내가 원래 그 객체를 생성하고 살리고 하는 주제 제어자 였는데,
Dependency Injection에 의하여 내가 주입을 받는 대상자가 되어 버렷다.
따라서 저어가 역행하게 된것이다.
결합된 코드 즉, 밀접하게 연관이 된 코드는 테스트하고 재 사용할 시 어려우며 이해하기도 어렵다. 때문에 결합도를 낮추어서 의존하는 객체들 간 협업을 조정하는 책임이 객체 자체로부터 분리되어 나간 것을 말한다.
스피링에서의 AOP
1. POJO기반 AOP적용
기존에 우리는 특정 클래스(객체)를 공통적으로 사용할 필요성이 있을 때
특히 보안, 트랜잭션, 공통 기능(Common Class, Common Method같은 것들)을 여러 개의 서로 다른 객체들에서 접근하여 사용하려 할 때 일일이 생성하고 메소드를 불러서 써야 했다.
예를 들어 사용자가 입력한(이름, 주소, 학력, 각종 개인정보에 대하여 각기 다른 필드를 통해서 입력을 받을때) String객체를 암호화 하는 프로세스를 가진 간단한 프로그램이 있다고 가정할때, 각각의 정보들에 대하여 일일이 암호화하는(동일한 암호화 알고리즘으로..) 프로세스를 거쳐야 한다 (적절한 예인지는 잘 모르겠다;;) 생성된 객체에 대하여 일일이 메소드에 해당 값을 집어 넣은후 받아 와야 하는 번거로움이 생기며, 복잡한 의존성을 불필요하게 가지게 된다. 만에 하나 갑작스러운 요구 사항의 변경으로 필드를 하나 추가하거나, 필드를 삭제하게 될 때 해당 메소드를 부르는 작업을 추가 하거나 삭제 해야 한다. (깜빡하고 삭제하지 않으면 당연히 엑셉션이 발생하게 된다)
이는 매우 비 효율적인 것 임에 틀림없다.
때문에 나온 것이 AOP라는 기법이다.
AOP(Aspect Oriented Programming)란 공통 관심사항에 대하여 발생하는 복잡성과 코드 중복을 해소해 주는 프로그래밍 기법이다.
여기서 중요한 개념이 Aspect인데, 이 Aspect가 공통 모듈을 로직을 구현할 클래스에 적용된다.
(써놓고 보니 매우 난해하다;;;)
한마디로 말해 공통 관심사에 관해서 공통 관심사를 사용할 객체들이 직접 공통 관심사(공통 객체)를 생성 접근하는 것은 프로그램의 복잡도를 증가 시키고, 코드를 중복 시키고 결합도를 높여 객체지향적이지 못해지는 요인으로 작용하므로, 그렇게 하지 말고( 공통 관심사를 사용할 놈들이 직접 생성해서 지지고 볶고 하지 말고) 외부에서 따로 이쁘게 처리하자~! 이말이다.
예를 보자
<공통 관심사 클래스> - 아래의 클래스가 우리가 공통 관심사로서 사용할 클래스 이다.
public class LoggingAspect {
private Log log = LogFactory.getLog(getClass());
public Object logging(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("기록시작);
StopWatch stopWatch = new StopWatch();
try {
stopWatch.start();
Object retValue = joinPoint.proceed();
return retValue;
} catch (Throwable e) {
throw e;
} finally {
stopWatch.stop();
log.info("기록종료);
log.info(joinPoint.getSignature().getName() + "메소드실행시간: "
+ stopWatch.getTotalTimeMillis());
}
}
}
그렇다면 이놈을 일일이 사용할 다른 여러 객체들에서 접근하지 말고 어떻게 쓸까?
<bean id="logging" class="kame.spring.chap01.LoggingAspect" />
<aop:config>
<aop:pointcut id="servicePointcut" expression="execution(* *..*Service.*(..))" />
<aop:aspect id="loggingAspect" ref="logging">
<aop:around pointcut-ref="servicePointcut" method="logging" />
</aop:aspect>
</aop:config>
이렇게 하면, expression="execution(* *..*Service.*(..))" />에 의해서 Service로 끝나는 인터페이스를 구현한 객체들에 대하여 우리의 공통 관심사 객체가 적용이 되게 된다.
음 . . 보다 자세한 내용은 좀 더 공부 해보아야 겠다 . 일단 DI와 AOP맛보기는 끝~!
(출처 및 인용 : 최범균님의 Spring 2.5 Programming, Spring in Action이 참 이해하기 쉽게 잘되어 있다 두책을 번갈아 보면서 공부하면 매우 효율적이다. 그리고 나는 가메 출판사에서 나오는 관련 전공 서적들에 항상 매력을 느낀다 . . Struts때도 그랫고 . . EJB3.0도 그렇고 . .)
'Computer Science' 카테고리의 다른 글
| 스프링 - 아이바티스 연동 (0) | 2011.11.02 |
|---|---|
| Spring 3 MVC 핼로 월드 예제 (0) | 2011.11.01 |
| [JSP/JAVA] 최상위, 파일 경로 알아내기 (0) | 2011.10.26 |
| JUnit을 이용한효율적인테스트전략 (0) | 2011.10.25 |
| 지능형지속위협(APT)공격, 99.999% 당한다 (0) | 2011.10.16 |