Transaction 사용하기
Transaction 를 사용하기 위해서는 그룹 설정을 해줘야 한다.
service.xml 설정
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
<context:component-scan base-package="bit.java39.dao, bit.java39.service">
<tx:annotation-driven transaction-manager="transactionManager"/>
serviceImpl.java 설정
@Transactional(rollbackFor=Exception.class)
Aspect-oriented programming
service.xml
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
LoggingAspect.java
@Aspect
@Component
public class LoggingAspect {
// fully-qualified name(QName) = 패키지명 + 클래스명
// AspectJ poingcut expression
// execution(메소드 범위 리턴타입 QName.메소드명(파라미터들)
// 예) execution(public int net.bitacademy.**.add(*))
// @Before("execution(* bit.java39.dao.*.*(..))")//("표현식")
// @Before("execution(* *.*(..))")//("표현식")
@Before("execution(* *..dao.*.*(..))")//("표현식")
public void logBefore(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getDeclaringTypeName());
System.out.println(joinPoint.getSignature().getName());
System.out.println(Arrays.toString(joinPoint.getArgs()));
System.out.println("============================> 이전...");
}
@After("execution(* *..dao.*.*(..))")//("표현식")
public void logAfter(){
System.out.println("==============================> 이후....");
}
}
AspectJ의 Pointcut 표현식
□ POJO 클래스를 이용하여 AOP를 적용하는 두 가지 방법
- XML 스키마를 이용하여 Aspect를 설정하는 방법.
- @Aspect 어노테이션을 이용하여 Aspect를 설정하는 방법.
■ 두 방법의 공통점
- AspectJ의 문법을 이용하여 Pointcut을 설정.
■ <aop:태그>를 이용하여 Aspect를 설정하는 경우
- execution 명시자를 이용하여 Advice가 적용될 Pointcut을 설정.
<aop:aspect id="cacheAspect" ref="cache">
<aop:around method="read"
pointcut="execution(public * kame.spring.chap03.core.*.readArticle(..))" />
</aop:aspect>
□ AspectJ의 Pointcut 표현식
- AspectJ는 Pointcut을 명시할 수 있는 다양한 명시자를 제공.
- 스프링은 메서드 호출과 관련된 명시자만을 지원.
■ execution 명시자
- Advice를 적용할 메서드를 명시할 때 사용.
○ 기본 형식
execution(수식어패턴? 리턴타입패턴 패키지패턴?이름패턴(파라미터패턴)
● 수식어 패턴
- 생략가능한 부분.
- public, protected 등이 옴.
● 리턴타입패턴
- 리턴 타입을 명시
● 클래스이름 패턴, 이름패턴
- 클래스 이름 및 메서드 이름을 패턴으로 명시.
● 파라미터패턴
- 매칭될 파라미터에 대해서 명시.
○ 특징
- 각 패턴은 '*'를 이용하여 모든 값을 표현.
- '..'을 이용하여 0개 이상이라는 의미를 표현.
○ 설정 예
● execution(public void set*(..))
- 리턴 타입이 void이고 메서드 이름이 set으로 시작하고, 파라미터가 0개 이상인 메서드 호출.
● execution(* kame.spring.chap03.core.*.*())
- kame.spring.chap03.core 패키지의 파라미터가 없는 모든 메서드 호출.
● execution(*.kame.spring.chap03.core..*.*(..))
- kame.spring.chap03.core 패키지 및 하위 패키지에 있는 파라미터가 0개 이상인 메서드 호출.
● execution(Integer kame.spring.chap03.core.WriteArticleService.write(..))
- 리턴 타입이 Integer인 WriteArticleService 인터페이스의 write() 메서드 호출.
● execution(* get*(*))
- 이름이 get으로 시작하고 1개의 파라미터를 갖는 메서드 호출.
● execution(* get*(*, *))
- 이름이 get으로 시작하고 2개의 파라미터를 갖는 메서드 호출.
● execution(* read*(Integer, ..))
- 메서드 이름이 read로 시작하고, 첫 번째 파라미터 타입이 Integer이며, 1개 이상의 파라미터를 갖는 메서드 호출.
■ within 명시자
- 메서드가 아닌 특정 타입에 속하는 메서드를 Pointcut으로 설정할 때 사용.
○ 설정 예
● within(kame.spring.chap03.core.WriteArticleService)
- WriteArticleService 인터페이스의 모든 메서드 호출.
● within(kame.spring.chap03.core.*)
- kame.spring.chap03.core 패키지에 있는 모든 메서드 호출.
● within(kame.spring.chap03.core..*)
- kame.spring.chap03.core 패키지 및 그 하위 패키지에 있는 모든 메서드 호출.
■ bean 명시자
- 스프링 2.5 버전부터 스프링에서 추가적으로 제공하는 명시자.
- 스프링 빈 이름을 이용하여 Pointcut을 정의.
- 빈 이름의 패턴을 갖는다.
○ 설정 예
● bean(writeArticleService)
- 이름이 writeArticleService인 빈의 메서드 호출.
● bean(*ArticleService)
- 이름이 ArticleServie로 끝나는 빈의 메서드 호출.
■ 표현식 연결
- 각각의 표현식은 '&&' 나 '||' 연산자를 이용하여 연결 가능.
○ @Aspect 어노테이션을 이용하는 경우
- '&&' 연산자를 사용하여 두 표현식을 모두 만족하는 Joinpoint에만 Advice가 적용.
@AfterThrowing(
pointcut = "execution(public * get*()) && execution(public void set*(..))")
public void throwingLogging() {
...
}
○ XML 스키마를 이용하여 Aspect를 설정하는 경우
- '&&'나 '||' 연산자를 사용.
<aop:pointcut id="propertyMethod"
expression="execution(public * get*()) && execution(public void set*(..))" />
- XML 문서이기 때문에 값에 들어가는 '&&' '||'를 '&&'로 표현.
- 설정파일에서 '&&'나 '||' 대신 'and'와 'or'를 사용할 수 있도록 하고 있음.
<aop:pointcut id="propertyMethod"
expression="execution(public * get*()) and execution(public void set*(..))" />
□ 프록시 구현 방식에 따른 execution 적용 차이
- Pointcut은 실제로 프록시가 구현하고 있는 인터페이스를 기준으로 Pointcut을 적용.
- 인터페이스를 구현하고 있는 대상 객체에 대해서 Pointcut을 정의하려면 인터페이스를 기준으로 Pointcut을 작성.
<aop:aspect id="cacheAspect" ref="cache">
<aop:around method="read"
pointcut="execution(public * kame..core.ReadArticleServiceImpl.get*(..))" />
</aop:aspect>
<bean id="readArticleService" class="kame.spring.chap03.core.ReadArticleServiceImpl" />
- ReadArticleServiceImpl 클래스가 ReadArticleService 인터페이스를 구현하고 있다면,
<aop:around>는 ReadArticleServiceImpl 클래스의 get으로 시작하는 메서드에 적용.
(<aop:around> 태그에서 명시한 Pointcut은 readArticleService 빈에는 적용되지 않음.)
- ReadArticleServiceImpl 클래스가 인터페이스를 구현하고 있지 않다면,
생성된 프록시는 ReadArticleServiceImpl 클래스를 상속받아 생성됨. (Pointcut은 readArticleService 빈에만 적용.)
transaction =>> insert, update, delete
transaction
프로그래밍 (직접 코딩) coding
filter(by aop) coding (코딩) aop ==> 메소드 앞 뒤로 지정
annotation 서버에서 직접 작업(유지보수에 좋다)
ownership – 서비스는 여러개의 Dao를 사용 가능하다.
Signature() 메서드 선언규칙 ==> 리턴타입 메소드명(파라미터)
RECENT COMMENT