๐ปSpring AOP
- AOP : Aspect Oriented Programming
- ๊ด์ ์งํฅ ํ๋ก๊ทธ๋๋ฐ
- ๊ด์ (=๊ด์ฌ์ฌ)๋ ์ ๋ฌด ๊ตฌํ์ ์ฃผ์ ๋ฌด๊ฐ ์๋ ๋๋จธ์ง ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์๋ฏธํ๋ค.
- ํก๋จ ๊ด์ฌ์ฌ๋ฅผ ๋ณ๋์ ๋ชจ๋๋ก ๋ถ๋ฆฌํ์ฌ ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ํฅ์์ํจ๋ค.
- Spring AOP๋ ์ฃผ๋ก ์ด๋ ธํ ์ด์ ๋๋ XML ์ค์ ์ ํตํด ๊ด์ฌ์ฌ๋ฅผ ์ ์ํ๊ณ , ์ด๋ฅผ ํต์ฌ ๋ก์ง์ ์ ์ฉํ์ฌ ํก๋จ ๊ด์ฌ์ฌ๋ฅผ ์ฒ๋ฆฌํ๋ค.
โป๊ธฐ์กด ๋ฐฉ์๊ณผ AOP ๋ฐฉ์ ๋น๊ต
๊ธฐ์กด ๋ฐฉ์
- ๊ฒ์ํ ๊ธ์ฐ๊ธฐ์ add.do ํ์ผ
- ์ฃผ์ ๋ฌด : ๊ธ์ฐ๊ธฐ ๊ธฐ๋ฅ
- ๋ณด์กฐ์ ๋ฌด : ๊ถํ ์ฒดํฌ
- ์ฃผ์ ๋ฌด์ ๋ณด์กฐ์ ๋ฌด๋ฅผ ํ ํ์ผ์์ ๊ตฌํํ๋ค.
- ์ด๋๊น์ง ์ฃผ์ ๋ฌด๊ณ ๋ณด์กฐ์ ๋ฌด์ธ์ง ์ฝ๋ ๊ด๋ฆฌ๊ฐ ๋ถํธํ๋ค๋ ๋จ์ ์ด ์๋ค.
AOP ๋ฐฉ์
- ์ฃผ์ ๋ฌด์ ๋ณด์กฐ์ ๋ฌด๋ฅผ ๋ถ๋ฆฌ์์ผ์ ๋ฐ๋ก ๊ตฌํํ๋ค.
- ์คํ๋ง์ ํตํด์ ์ฃผ์ ๋ฌด์ ๋ณด์กฐ์ ๋ฌด๋ฅผ ๋ค์ ๊ฒฐํฉ ํ ๋์ํ๋ค.
Spring AOP ์ฉ์ด
1. Core Concern
- ๋น์ฆ๋์ค ์ฝ๋, ์ฃผ์ ๋ฌด
- ์ดํ๋ฆฌ์ผ์ด์ ์ ํต์ฌ ๋ชฉ์ ์ ๋ฌ์ฑํ๊ธฐ ์ํ ์ฃผ์ ๊ธฐ๋ฅ๋ค์ ํฌํจํ๋ฉฐ, ์ฃผ๋ก ๊ฐ๋ฐ์๊ฐ ์ง์ ์ฝ๋๋ก ์์ฑํ๋ ๋ถ๋ถ
2. Cross-cutting Concern
- ๋ณด์กฐ์ ๋ฌด
- ์ฃผ๋ก ๋ก๊น , ํธ๋์ญ์ ๊ด๋ฆฌ, ๋ณด์ ๋ฑ๊ณผ ๊ฐ์ด ์ฌ๋ฌ ๋ชจ๋์์ ๊ณตํต์ผ๋ก ํ์ํ ๋ถ๋ถ์ ํฌํจํ๋ค.
- AOP๋ ํก๋จ ๊ด์ฌ์ฌ๋ฅผ ๋ชจ๋ํํ๊ณ ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๊ธฐ ์ํ ๋ชฉ์ ์ผ๋ก ๋์ ๋์๋ค. AOP๋ ํต์ฌ ๊ด์ฌ์ฌ์ ํก๋จ ๊ด์ฌ์ฌ๋ฅผ ๋ถ๋ฆฌํ์ฌ ๊ฐ๋ฐ์๊ฐ ํต์ฌ ๋ก์ง์๋ง ์ง์คํ ์ ์๋๋ก ๋์์ค๋ค.
3. Target
- ๋น์ฆ๋์ค ์ ๋ฌด๋ฅผ ์์ ํ ๊ฐ์ฒด
- ์ฃผ์ ๊ธฐ๋ฅ์ด๋ ๋น์ฆ๋์ค ๋ก์ง์ ๋ด๋นํ๋ ๊ฐ์ฒด๋ก, AOP์์๋ ๋ณด์กฐ ์ ๋ฌด๊ฐ ์ ์ฉ๋๋ ๋์์ด ๋๋ค.
4. Proxy
- Target์ ๊ฐ์ธ๋ ๋๋ฆฌ ๊ฐ์ฒด
- AOP์์๋ ์ฃผ๋ก ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์ ์ฉํ๊ธฐ ์ํ ์ฉ๋๋ก ์ฌ์ฉ๋๋ค.
- ํด๋ผ์ด์ธํธ๊ฐ ์ค์ Target์ด ์๋ Proxy์ ์ ๊ทผํ๊ฒ ๋๋ฉด, Proxy๋ ํ์ํ ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์ฒ๋ฆฌํ ํ์ ์ค์ Target์๊ฒ ์ ์ด๋ฅผ ์ ๋ฌํ๋ค.
5. JoinPoint
- Target์ด ๊ฐ์ง ์ฃผ์ ๋ฌด(๋ฉ์๋)
- AOP์์๋ ์ด JoinPoint์ ๋ณด์กฐ ์ ๋ฌด(Advice)๋ฅผ ์ ์ฉํ์ฌ ํก๋จ ๊ด์ฌ์ฌ๋ฅผ ์ฒ๋ฆฌํ๋ค.
6. Pointcut
- ๋ณด์กฐ์ ๋ฌด์ ํน์ JoinPoint๋ฅผ ์ฐ๊ฒฐํ๋ ์์
- ์ด๋ค ๋ฉ์๋๋ฅผ ์ธ์ ์คํํ ์ง๋ฅผ ๊ฒฐ์ ํ๋๋ฐ ์ฌ์ฉ๋๋ค.
- Pointcut์ ์ ๊ท ํํ์ ๋๋ ํจํด์ ํตํด JoinPoint๋ฅผ ์ ํํ๋ค.
7. Aspect
- ๋ณด์กฐ์ ๋ฌด๋ฅผ ๊ตฌํํ๋ ๊ฐ์ฒด
- Aspect๋ Pointcut๊ณผ Advice๋ฅผ ๊ฒฐํฉํ์ฌ ์ค์ ๋ก ์ด๋ค ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์ํํ ์ง๋ฅผ ์ ์ํ๋ค. ๋ณด์กฐ ์ ๋ฌด๋ ์ฃผ๋ก ํก๋จ ๊ด์ฌ์ฌ๋ฅผ ์ฒ๋ฆฌํ๋๋ฐ ์ฌ์ฉ๋๋ค.
8. Advice
- ์ฃผ์ ๋ฌด๊ฐ ์ํ๋๋ ์ด๋ ์์ ์ ๋ณด์กฐ์ ๋ฌด๋ฅผ ์คํํ ์ง ์ ์ํ๋ ๊ฒ
- Before Advice: ์ฃผ์ ๋ฌด ์คํ ์ ์ ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์คํํ๋ค.
- After Advice: ์ฃผ์ ๋ฌด ์คํ ํ์ ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์คํํ๋ค.
- Around Advice: ์ฃผ์ ๋ฌด๋ฅผ ๊ฐ์ธ์ ์ /ํ์ ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์คํํ๋ฉฐ, ์ฃผ์ ๋ฌด๋ฅผ ์ง์ ์คํ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ ์ ์๋ค.
- After-returning Advice: ์ฃผ์ ๋ฌด๊ฐ ์ ์์ ์ผ๋ก ์คํ๋ ํ์ ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์คํํ๋ค.
- After-throwing Advice: ์ฃผ์ ๋ฌด์์ ์์ธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ์ ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์คํํ๋ค.
๐ปSpring AOP ๊ตฌํ
- com.test.spring.aop1 ํจํค์ง ์์ฑ
- ํ์ ํ์ผ ์์ฑ
- Main.java
- Memo.java (I) : ๋ฉ์ธ ์ ๋ฌด ๊ฐ์ฒด(์ธํฐํ์ด์ค)
- MemoImpl.java(C) : ๋ฉ์ธ ์ ๋ฌด ๊ฐ์ฒด(ํด๋์ค)
- Logger.java(C) : ๋ณด์กฐ ์ ๋ฌด ๊ฐ์ฒด(ํด๋์ค)
- memo.xml : ์คํ๋ง ์ค์ ํ์ผ
๊ณ์ธต๊ณผ ๊ณ์ธต ์ฌ์ด์ ๊ด๊ณ
์๋ธ๋ฆฟ ๊ณ์ธต๊ณผ ๊ณ์ธต ์ฌ์ด์ ๊ด๊ณ๋ฅผ ํด๋์ค๋ก ๋ง๋ค์ด ์ด์ด์คฌ๋ค. (DAO <-> Controller <-> View)
Spring์์ ๊ณ์ธต ์ฌ์ด์ ๊ด๊ณ๋ฅผ ์ธํฐํ์ด์ค๋ก ๋ง๋ ๋ค.
Main.java
๋ฉ๋ชจ ๋ฑ๋ก, ์กฐํ, ์์ , ์ญ์ ๋ฅผ ํธ์ถํ๋ค.
package com.test.spring.aop1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("com/test/spring/aop1/memo.xml");
Memo memo = (Memo)context.getBean("memo"); //new MemoImpl()์ ๋์ผํ ์ญํ
memo.add("์คํ๋ง AOP");
try {
String txt = memo.read(15);
System.out.println(txt);
} catch (Exception e) {
e.printStackTrace();
}
memo.edit(5, "์์ ํฉ๋๋ค.");
memo.del(5);
}
}
์ฃผ์ ๋ฌด ๊ฐ์ฒด ์์ฑ
์ฃผ์ ๋ฌด ๊ฐ์ฒด์ธ memo๋ฅผ ์ง์ ์์ฑํ๋ฉด ์คํ๋ง ํ๊ฒฝ์ ์ ๊ณต๋ฐ์ง ๋ชปํ๋ค. ๊ทธ๋ฌ๋ฏ๋ก ์คํ๋ง์ ํตํด ์์ฑํ์ฌ ์คํ๋ง์ ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์๋๋ก ํ๋ค.
ApplicationContext context = new ClassPathXmlApplicationContext("com/test/spring/aop1/memo.xml");
ApplicationContext ์ธํฐํ์ด์ค
ApplicationContext๋ Spring ์ปจํ
์ด๋๋ฅผ ๋ํ๋ด๋ ์ธํฐํ์ด์ค์ด๋ค. Spring ์ ํ๋ฆฌ์ผ์ด์
์์ ๋น(Bean)๋ค์ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ค.
ClassPathXmlApplicationContext ํด๋์ค
XML ํ์์ ์ค์ ํ์ผ์ ์ด์ฉํ์ฌ Spring ApplicationContext๋ฅผ ์์ฑํ๋ ๊ตฌํ์ฒด ์ค ํ๋์ด๋ค. ์ง์ ๋ ํด๋์ค ํจ์ค์์ XML ์ค์ ํ์ผ์ ์ฐพ์ ์ฝ์ด๋ค์ฌ ApplicationContext๋ฅผ ์ด๊ธฐํํ๋ค.
ClassPathXmlApplicationContext๋ ํด๋์ค ํจ์ค ์์์ ์ง์ ๋ ๊ฒฝ๋ก์์ XML ์ค์ ํ์ผ์ ์ฐพ์ ์ฌ์ฉํ๋ค.
Bean ๊ฐ์ ธ์ค๊ธฐ
Memo memo = (Memo)context.getBean("memo");
context๋ ์์ ์์ฑํ ApplicationContext์ผ๋ก getBean ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ApplicationContext์์ ๋น์ ๊ฐ์ ธ์จ๋ค.
"memo"๋ ๊ฐ์ ธ์ค๊ณ ์ ํ๋ ๋น์ ์ด๋ฆ์ด๋ฉฐ, ์ด๋ XML ์ค์ ํ์ผ์์ ํด๋น ๋น์ <bean> ํ๊ทธ์ id ์์ฑ์ ์ง์ ๋ ๊ฐ๊ณผ ์ผ์นํด์ผ ํ๋ค.
Memo.java
๋ฉ๋ชจ ์ฐ๊ธฐ, ์ฝ๊ธฐ, ์์ , ์ญ์ ํ๊ธฐ๋ฅผ ์ ์ธํ๋ค.
package com.test.spring.aop1;
public interface Memo {
//๋ฉ๋ชจ ์ฐ๊ธฐ
void add(String memo);
//๋ฉ๋ชจ ์ฝ๊ธฐ
String read(int seq);
//๋ฉ๋ชจ ์์
boolean edit(int seq, String memo);
//๋ฉ๋ชจ ์ญ์
boolean del(int seq);
}
MemoImpl.java
์ฃผ์ ๋ฌด(๋ฉ๋ชจ ์ฐ๊ธฐ, ์ฝ๊ธฐ, ์์ , ์ญ์ )๋ฅผ ๊ตฌํํ๋ค.
package com.test.spring.aop1;
public class MemoImpl implements Memo{
@Override
public void add(String memo) {
System.out.println("๋ฉ๋ชจ ์ฐ๊ธฐ: " + memo);
}
@Override
public String read(int seq) throws Exception{
if (seq < 10) {
System.out.println("๋ฉ๋ชจ ์ฝ๊ธฐ");
} else {
throw new Exception("์กด์ฌํ์ง ์๋ ๋ฉ๋ชจ");
}
return "๋ฉ๋ชจ ์ฝ๊ธฐ ์๋ฃ";
}
@Override
public boolean edit(int seq, String memo) {
System.out.println("๋ฉ๋ชจ ์์ : " + memo);
return false;
}
@Override
public boolean del(int seq) {
System.out.println(seq + "๋ฒ ๋ฉ๋ชจ ์ญ์ ์๋ฃ");
return false;
}
}
Logger.java
๋ณด์กฐ์ ๋ฌด(๋ก๊ทธ ๊ธฐ๋ก)๋ฅผ ๊ตฌํํ๋ค. ๋ณด์กฐ์ ๋ฌด์ ํ์ด๋ฐ์ memo.xml ํ์ผ์์ ๊ด๋ฆฌํ๋ค.
package com.test.spring.aop1;
import java.util.Calendar;
import org.aspectj.lang.ProceedingJoinPoint;
public class Logger {
public void log() {
Calendar now = Calendar.getInstance();
System.out.printf("[LOG][%tF %tT] ๋ก๊ทธ๋ฅผ ๊ธฐ๋กํฉ๋๋ค.\n", now, now);
}
public void time(ProceedingJoinPoint jp) {
//์ฃผ์
๋ฌด๋ฅผ ์คํํ๋ ์์์๊ฐ
long begin = System.nanoTime();
System.out.println("[LOG] ๊ธฐ๋ก์ ์์ํฉ๋๋ค.");
//์ฃผ์
๋ฌด ์คํ > aop์ around์ ์ฌ์ฉ
//์ฃผ์
๋ฌด ๊ฐ์ฒด์ ๊ฐ์ ๊ฐ์ฒด ์ฐธ์กฐ
try {
jp.proceed(); //์ฃผ์
๋ฌด ๊ฐ์ฒด์ ์ฃผ์
๋ฌด ๋ฉ์๋๋ฅผ ์๋ฏธํ๋ค. xml์์ ์ง์ ํ๋ค.
} catch (Throwable e) {
e.printStackTrace();
}
long end = System.nanoTime();
System.out.println("[LOG] ๊ธฐ๋ก์ ์ข
๋ฃํฉ๋๋ค.");
System.out.printf("[LOG] ์ผ์ ์๊ฐ %,dns\n", end-begin);
}
public void history(String memo) {
System.out.println("[LOG] ์ฝ๊ธฐ ๊ธฐ๋ก > " + memo);
}
public void check(Exception e) {
//์์ธ์ฒ๋ฆฌ๊ฐ ์๋ ์๋ฌ๋ฉ์์ง๋ง ์ถ๋ ฅํ๋ ์ญํ
System.out.println("[LOG]์์ธ ๋ฐ์: " + e.getMessage());
}
}
AOP ์์ฑํ๊ธฐ
#AOP๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ํ๊ฒฝ์ค์
1. Namespace
xml ํ์ผ ์ฐํด๋ฆญ - Spring - Add as Bean Configuration
xml ํ๋ฉด ํ๋จ์ ์ฌ๋ฌ๊ฐ์ ํญ์ด ์๊ฒผ๋ค.
'Namespaces' ํญ์์ aop ์ฒดํฌ๋ฅผ ํ๊ณ ํ์ผ์ ์ ์ฅํ๋ค.
2. jar ์ค์น
pom.xml์ ์๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ค.
<!-- AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
memo.xml
1. ์ฃผ์ ๋ฌด ๊ฐ์ฒด ๋ฐ ๋ณด์กฐ ์ ๋ฌด ๊ฐ์ฒด ์ ์
<!-- ์ฃผ์
๋ฌด ๊ฐ์ฒด -->
<bean id="memo" class="com.test.spring.aop1.MemoImpl"></bean>
<!-- ๋ณด์กฐ ์
๋ฌด ๊ฐ์ฒด -->
<bean id="logger" class="com.test.spring.aop1.Logger"></bean>
์ฃผ์ ๋ฌด ๊ฐ์ฒด( MemoImpl)์ ๋ณด์กฐ์ ๋ฌด ๊ฐ์ฒด(Logger) ๊ฒฐํฉํ๋ ๊ฒ์ด memo.xml์ ์ ๋ฌด์ด๋ค.
๊ฒฐํฉํ๊ธฐ ์ํด ๊ฐ์ฒด๋ฅผ ์ธ์งํ๋ ๋จ๊ณ๋ฅผ ๋จผ์ ๊ฑฐ์ณ์ผํ๋๋ฐ <bean> ์ผ๋ก ์ ์ธํ๋ฉด ์คํ๋ง์ด ํน์ ๊ฐ์ฒด(ํด๋์ค)๋ฅผ ์ธ์งํ ์ ์๋ค.
2. AOP ์ค์
<aop:config>
<aop:aspect id="loggerAspect" ref="logger">
<!-- Aspect ๋ด์ฉ์ด ์ด์ด์ง ๋ถ๋ถ -->
</aop:aspect>
</aop:config>
์ฃผ์ ๋ฌด ๊ฐ์ฒด์ ๋ณด์กฐ์ ๋ฌด ๊ฐ์ฒด ๊ฒฐํฉ์ AOP๊ฐ ๋ด๋นํ๋ค.
aop ํ๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ AOP ์ค์ ํ๋ค.
aspect ๋ ๋ณด์กฐ์ ๋ฌด๋ฅผ ๋ด๋นํ๋ ๊ฐ์ฒด๋ก์จ loggerAspect๋ผ๋ ์ด๋ฆ์ Aspect๋ฅผ ์ ์ํ๊ณ , ์ด Aspect์ ๋ณด์กฐ ์ ๋ฌด๋ฅผ ๊ตฌํํ logger ๋น์ ์ฐธ์กฐํ๋ค.
aspect : ๋ณด์กฐ์ ๋ฌด ๋ด๋น ๊ฐ์ฒด
3. Pointcut ์ ์
1) PointCut ์ง์ ํ๊ธฐ
- ์ฃผ์ ๋ฌด ๊ฐ์ฒด ์ง์ ๋ฐ ๋ฉ์๋๋ฅผ ์ฐพ๋๋ค. ์ฃผ์ ๋ฌด ์ฌ์ด์์ ๋ณด์กฐ์ ๋ฌด๊ฐ ์คํํ๋ ์์ ์ ์ ํ๋ค.
- ex) MemoImpl.add ๋ฉ์๋, MemoImpl.read ๋ฉ์๋
2) AspectJ ํํ์์ ์ฌ์ฉํ์ฌ ์ฐพ๋๋ค.
- AspectJ ํํ์์ ๋ ๋ฆฝ์ ์ธ ํํ์์ผ๋ก Spring์์ ๊ฐ์ ธ๋ค ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
- execution() ์ง์์
- within() ์ง์์
3) execution()
- execution([์ ๊ทผ์ง์ ์] ๋ฐํํ [ํด๋์ค].๋ฉ์๋(์ธ์))
4) ์์ผ๋ ์นด๋ ์กด์ฌ
- * : ์ ๊ทผ์ง์ ์, ๋ฐํํ, ํจํค์ง, ํด๋์ค, ๋ฉ์๋์์ ์ฌ์ฉ๊ฐ๋ฅํ๋ค.
- .. : ์ธ์ ๋ฆฌ์คํธ์๋ง ์ฌ์ฉ๊ฐ๋ฅํ๋ค.
<!-- ๋ฉ๋ชจ ์ฐ๊ธฐ -->
<aop:pointcut expression="execution(public void com.test.spring.aop1.MemoImpl.add(String))" id="p1"/>
<!-- ๋ฉ๋ชจ ์ฝ๊ธฐ -->
<aop:pointcut expression="execution(public String com.test.spring.aop1.MemoImpl.read(int))" id="p2"/>
<!-- ์ฃผ์
๋ฌด์ ๋ณด์กฐ์
๋ฌด๊ฐ ๊ฐ์ ํจํค์ง ๋ด์ ์๋ค๋ฉด ํจํค์ง์ ํด๋์ค ์ด๋ฆ์ ์๋ตํ ์ ์๋ค. -->
<aop:pointcut expression="execution(public void add(String))" id="p4"/>
<!-- ์์ผ๋ ์นด๋๋ฅผ ์ฌ์ฉํด์ ๋ชจ๋ ๋ฉ์๋(CRUD)๋ฅผ ์ฐพ๋๋ค. -->
<aop:pointcut expression="execution(* com.test.spring.aop1.MemoImpl.*(..))" id="p5"/>
<!-- a๋ก ์์ํ๋ ๋ชจ๋ ๋ฉ์๋ -->
<aop:pointcut expression="execution(* com.test.spring.aop1.MemoImpl.a*(..))" id="p6"/>
<!-- a๋ก ๋๋๋ ๋ชจ๋ ๋ฉ์๋ -->
<aop:pointcut expression="execution(* com.test.spring.aop1.MemoImpl.*a(..))" id="p7"/>
<aop:pointcut> ํ๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ Pointcut์ ์ ์ํ๋ค. Pointcut์ ์ด๋ค ๋ฉ์๋์ ์ด๋ค Advice๋ฅผ ์ ์ฉํ ์ง๋ฅผ ๊ฒฐ์ ํ๋๋ฐ ์ฌ์ฉ๋๋ค.
4. Advice ์ ์ฉ
- Advice๋ ์ฃผ์ ๋ฌด๊ฐ ์ํ๋๋ ์ด๋ ์์ ์ ๋ณด์กฐ์ ๋ฌด๋ฅผ ์คํํ ์ง ์ ์ํ๋ ๊ฒ์ด๋ค.
- ๋ณด์กฐ์ ๋ฌด ๊ฐ์ฒด์ ๋ฉ์๋๋ช ๊ณผ + ํฌ์ธํธ์ปท์ id ๋ก ์ง์ ํ๋ค.
- 5์ข
๋ฅ Advice ์ค ํ๋๋ฅผ ์ค์ ํ๋ค.
- Before Advice: ์ฃผ์ ๋ฌด ์คํ ์ ์ ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์คํํ๋ค.
- After Advice: ์ฃผ์ ๋ฌด ์คํ ํ์ ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์คํํ๋ค.
- Around Advice: ์ฃผ์ ๋ฌด๋ฅผ ๊ฐ์ธ์ ์ /ํ์ ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์คํํ๋ฉฐ, ์ฃผ์ ๋ฌด๋ฅผ ์ง์ ์คํ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ ์ ์๋ค.
- After-returning Advice: ์ฃผ์ ๋ฌด๊ฐ ์ ์์ ์ผ๋ก ์คํ๋ ํ์ ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์คํํ๋ค.
- After-throwing Advice: ์ฃผ์ ๋ฌด์์ ์์ธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ์ ๋ณด์กฐ ์ ๋ฌด๋ฅผ ์คํํ๋ค.
<aop: 'advice'> ํ๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฉํ๋ค.
after
<aop:after method="log" pointcut-ref="p1"/>
๋ณด์กฐ์
๋ฌด์ log ๋ฉ์๋๋ฅผ PointCut p1 ๋ค์ ์คํํ๊ฒ ๋ค๋ ์๋ฏธ์ด๋ค.
before
<aop:before method="log" pointcut-ref="p1"/>
๋ณด์กฐ์ ๋ฌด์ log ๋ฉ์๋๋ฅผ PointCut p1 ์ ์ ์คํํ๊ฒ ๋ค๋ ์๋ฏธ์ด๋ค.
around
<aop:around method="time" pointcut-ref="p5"/>
๋ณด์กฐ์ ๋ฌด์ time ๋ฉ์๋๋ฅผ PointCut p5 ์, ๋ค์ ์คํํ๊ฒ ๋ค๋ ์๋ฏธ์ด๋ค.
around๋ฅผ ์ฌ์ฉํ ๋ ๋ณด์กฐ์ ๋ฌด ๋ฉ์๋์ ์ฃผ์ ๋ฌด ๊ฐ์ฒด์ ๊ฐ์ ๊ฐ์ฒด ์ฐธ์กฐํ์ฌ ์ฌ์ฉํ๋ค.
try {
jp.proceed(); //์ฃผ์
๋ฌด ๊ฐ์ฒด์ ์ฃผ์
๋ฌด ๋ฉ์๋๋ฅผ ์๋ฏธํ๋ค. xml์์ ์ง์ ํ๋ค.
} catch (Throwable e) {
e.printStackTrace();
}
around๋ ๋ณด์กฐ์ ๋ฌด๊ฐ ์ฃผ์ ๋ฌด๋ฅผ ๊ฐ์ธ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ง์์ ์ฌ์ฉ๋น๋๊ฐ ๋ฎ๋ค.
after-returning
<aop:after-returning method="history" pointcut-ref="p2" returning="memo"/>
p2 Pointcut์์ ๋ฉ์๋๊ฐ ์ ์์ ์ผ๋ก ์คํ๋ ํ์, "history"๋ผ๋ ์ด๋ฆ์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด์ ํด๋น ๋ฉ์๋์ ๋ฐํ๋ Memo ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ค.
after-throwing
<aop:after-throwing method="check" pointcut-ref="p2" throwing="e"/>
p2 Pointcut์์ ๋ฉ์๋๊ฐ ์์ธ๋ฅผ ๋์ง ๋, "check"๋ผ๋ ์ด๋ฆ์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด์ ํด๋น ๋ฉ์๋์ ๋ฐ์ํ ์์ธ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ค.
์ ์ฒด memo.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- ์ฃผ์
๋ฌด ๊ฐ์ฒด -->
<bean id="memo" class="com.test.spring.aop1.MemoImpl"></bean>
<!-- ๋ณด์กฐ ์
๋ฌด ๊ฐ์ฒด -->
<bean id="logger" class="com.test.spring.aop1.Logger"></bean>
<!-- ์ฃผ์
๋ฌด ๊ฐ์ฒด์ ๋ณด์กฐ์
๋ฌด ๊ฐ์ฒด ๊ฒฐํฉ์ AOP๊ฐ ๋ด๋นํ๋ค.-->
<aop:config>
<aop:aspect id="loggerAspect" ref="logger">
<!-- ๋ฉ๋ชจ ์ฐ๊ธฐ -->
<aop:pointcut expression="execution(public void com.test.spring.aop1.MemoImpl.add(String))" id="p1"/>
<!-- ๋ฉ๋ชจ ์ฝ๊ธฐ -->
<aop:pointcut expression="execution(public String com.test.spring.aop1.MemoImpl.read(int))" id="p2"/>
<!-- ๋ฉ๋ชจ ์ฐ๊ธฐ + ์ฝ๊ธฐ (๋จ, ํํ์์ด ๋ณต์กํด์ง๊ธฐ์ ์ ์ฌ์ฉํ์ง ์๋๋ค)-->
<aop:pointcut expression="execution(public String com.test.spring.aop1.MemoImpl.read(int))
|| execution(public void com.test.spring.aop1.MemoImpl.add(String))" id="p3"/>
<!-- ์ฃผ์
๋ฌด์ ๋ณด์กฐ์
๋ฌด๊ฐ ๊ฐ์ ํจํค์ง ๋ด์ ์๋ค๋ฉด ํจํค์ง์ ํด๋์ค ์ด๋ฆ์ ์๋ตํ ์ ์๋ค. -->
<aop:pointcut expression="execution(public void add(String))" id="p4"/>
<!-- ์์ผ๋ ์นด๋๋ฅผ ์ฌ์ฉํด์ ๋ชจ๋ ๋ฉ์๋(CRUD)๋ฅผ ์ฐพ๋๋ค. -->
<aop:pointcut expression="execution(* com.test.spring.aop1.MemoImpl.*(..))" id="p5"/>
<!-- a๋ก ์์ํ๋ ๋ชจ๋ ๋ฉ์๋ -->
<aop:pointcut expression="execution(* com.test.spring.aop1.MemoImpl.a*(..))" id="p6"/>
<!-- a๋ก ๋๋๋ ๋ชจ๋ ๋ฉ์๋ -->
<aop:pointcut expression="execution(* com.test.spring.aop1.MemoImpl.*a(..))" id="p7"/>
<!-- <aop:after method="log" pointcut-ref="p1"/> -->
<!-- <aop:before method="log" pointcut-ref="p1"/> -->
<!--
<aop:after method="log" pointcut-ref="p1"/>
<aop:after method="log" pointcut-ref="p2"/>
-->
<!-- <aop:after method="log" pointcut-ref="p3"/> -->
<!-- <aop:after method="log" pointcut-ref="p4"/> -->
<!-- <aop:after method="log" pointcut-ref="p5"/> -->
<!-- around๋ ์ฌ์ฉํ๊ธฐ ํ๋ค์ด์ ๋๋ ๋ณด์กฐ์
๋ฌด๊ฐ ์ฃผ์
๋ฌด๋ฅผ ๊ฐ์ธ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ง์์ ์ฌ์ฉ๋น๋๊ฐ ๋ฎ๋ค -->
<!-- <aop:around method="time" pointcut-ref="p5"/> -->
<!-- returning์ ๋งค๊ฐ๋ณ์ ์ด๋ฆ์ ์ฐธ์กฐํ๋ค. -->
<!-- <aop:after-returning method="history" pointcut-ref="p2" returning="memo"/> -->
<aop:after-throwing method="check" pointcut-ref="p2" throwing="e"/>
</aop:aspect>
</aop:config>
</beans>
'Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] @Controller ๊ธฐ์ด ๋ฐ ๋ฐ์ดํฐ ์ก์์ ํ๊ธฐ (0) | 2023.11.25 |
---|---|
[Spring] ์คํ๋ง ํ๋ก์ ํธ ์ค์ ์ผ๊ด ์ ์ฉ (0) | 2023.11.24 |
[Spring] Spring DI(์์กด ์ฃผ์ ) ์์ ๋ฐ xml๋ก ์์กด๊ด๊ณ ํ์ฑํ๊ธฐ (0) | 2023.11.22 |
[Spring] Spring Framework๋ (0) | 2023.11.21 |
[Spring] Spring Tool Suite (STS3) ์ฌ์ฉ๋ฒ (0) | 2023.11.21 |