0. ํ์ต ๋ชฉ์
- SELF INVOCATION์ด ๋ฌด์์ธ์ง, ์ธ์ ์ผ์ด๋๋์ง ์ดํดํ๋ค.
- ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ๋ฌด์์ธ์ง ์ดํดํ๋ค.
1. SELF INVOCATION ์ด๋?
AOP ๋งค์ปค๋์ฆ ์ฌ์ฉ ์ ๊ฒช์ ์ ์๋ ๋ถ์์ฉ ์ค ํ๋์ด๋ค.
ํน์ ๊ฐ์ฒด์ ๋ฉค๋ฒ ๋งค์๋ A๊ฐ ๊ฐ์ ๊ฐ์ฒด ๋ด๋ถ์ ๋งค์๋ B๋ฅผ ์ง์ ํธ์ถํ ๋, B์ ๊ฑธ๋ ค์๋ AOP๋ ๋ฌด์๋๋ ํ์์ด๋ค.
(1) ์์
๋ค์๊ณผ ๊ฐ์ ํด๋์ค TEST
๊ฐ ์กด์ฌํ๋ค๊ณ ํด๋ณด์.
public class Test {
public void methodAB(A a, B b) {
methodA(A a);
methodB(B b);
}
@Transactional
public void methodA(A a) {
repository.save(A a);
}
@Transactional
public void methodB(B b) {
repository.save(B b);
}
}
Test์ ๊ฐ์ฒด๋ฅผ test๋ผ๊ณ ํ์ ๋,test.methodAB(A a, B b)
๋ฅผ ํธ์ถํ๋ค๋ฉด, methodA์ methodB์ AOP ์ด๋
ธํ
์ด์
์ธ @Transactional
์ด ์ ์ฉ๋์ง ์์, ๋ฐ์ดํฐ ์ ์ฅ์ ์คํจํ๊ฒ ๋๋ค.
2. ๋ฐ์ ์ด์
๋ฐ์ ์ด์ ๋ ๋์ ๊ฐ์ฒด ํธ์ถ ์์๋ง BeanProxy
๋ฅผ ํธ์ถํ๋ AOP์ ๋งค์ปค๋์ฆ ๋๋ฌธ์ด๋ค.
AOP์ ๋์ ๊ณผ์ ์ ๊ฐ๋ตํ ์ค๋ช ํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
- AOP ์ด๋ ธํ ์ด์ ์ด ๋ฌ๋ ค ์๋ ๊ฐ์ฒด๋ Bean ๋ฑ๋ก ์ ํด๋น ๊ฐ์ฒด ์์ฒด๊ฐ ๋ฑ๋ก๋์ง ์๊ณ , ํด๋น ๊ฐ์ฒด ์ ์ฉ Bean Proxy๊ฐ ๋์ ๋ฑ๋ก๋๊ฒ ๋๋ค.
- AOP๋ฅผ ํ์ฉํ๋ ๊ฐ์ฒด๊ฐ ํธ์ถ๋์์ ์, Spring์ ๋์ ๊ฐ์ฒด ๋์ ์ Bean Proxy๋ฅผ ๋์ ์ฌ์ฉํ๋ค. ๋งค์๋์ ๋ถ์ฐฉ๋ AOP์ ์ข ๋ฅ๋ฅผ ์ฝ๊ณ ๊ทธ์ ๋ง๋ Interceptor๋ฅผ Proxy ๋ด๋ถ์ ํธ์ถํ๋ค.
- Interceptor๊ฐ ์ ์ ํ ์์ ์ ์คํ๋๊ณ , ํต์ฌ ๊ธฐ๋ฅ ๋งค์๋๋ Proxy๊ฐ ์ ์ ํ ์์ ์ ํธ์ถํ์ฌ ์์ ํ๋ค.
๋์ ๊ณผ์ ์ ๋ณด๋ฉด ๋์ ๊ฐ์ฒด๊ฐ ํธ์ถ๋์ด์ผ์ง๋ง AOP๊ฐ ์๋ํจ์ ์ ์ ์๋ค.
ํ์ง๋ง ์์ SELF INVOCATION
์ด ๋ฐ์ํ๋ ์์๋ฅผ ๋ณด๋ฉด, ๋ด๋ถ ๋งค์๋๋ค์ ๊ฐ์ฒด๋ฅผ ํธ์ถํ์ง ์๋๋ค. ๋ค๋ง ๋ด๋ถ์ ์๋ Method๋ฅผ ๋ฐ๋ก ์ฐ๊ณ ์์์ ์ ์ ์๋ค.
public void methodAB(A a, B b) {
methodA(A a);
methodB(B b);
}
๋ฐ๋ผ์, methodA()์ methodB() ์ AOP๋ ์๋ํ์ง ์๋๋ค.
(1) ์์
์ด๋ฒ์ ์ธ๋ถ ๋งค์๋์ธ methodAB()
์ ๋ค๋ฅธ AOP๊ฐ ์ ํ ์๋ ๊ฒฝ์ฐ๋ฅผ ์ดํด๋ณด์.
public class Test {
@Logging
public void methodAB(A a, B b) {
methodA(A a);
methodB(B b);
}
@Transactional
public void methodA(A a) {
repository.save(A a);
}
@Transactional
public void methodB(B b) {
repository.save(B b);
}
}
- ๋์ ๊ฐ์ฒด์ ๋ชจ์ต
๋ค์๊ณผ ๊ฐ์ด ๊ฐ์ฒด๊ฐ ์กด์ฌํ๋ค๊ณ ํด๋ณด๋ฉด, ์ธ๋ถ ๋งค์๋๋ ๋ก๊น ๋ถ๊ฐ ๊ธฐ๋ฅ์, ๋ด๋ถ ๋งค์๋๋ ํธ๋์ญ์ ๋ถ๊ฐ๊ธฐ๋ฅ์ ์ฌ์ฉํจ์ผ๋ก ๋์ด ๋ถ๋ฅด๋ Advice๊ฐ ๋ค๋ฅด๋ค.
- Proxy ๊ฐ์ฒด์ ๋ชจ์ต
ํด๋น ๋์ ๊ฐ์ฒด๋ฅผ bean์ ๋ฑ๋กํ ๋๋ AOP ์ด๋ ธํ ์ด์ ์ด ๋ด๋ถ์ ์์ผ๋ฏ๋ก ๋์ ๊ฐ์ฒด ์์ฒด ๋์ ์ Proxy ๊ฐ์ฒด๊ฐ ๋์ ๋ฑ๋ก๋๊ฒ ๋๋ค. ์์ ๊ทธ๋ฆผ์ Proxy ๊ฐ์ฒด์ ์์์ด๋ค.
- ๋งค์๋ ํธ์ถ
ํน์ ํจ์์์๋์ ๊ฐ์ฒด.methodAB()
๋ฅผ ํธ์ถํ๋ค๋ฉด, BeanProxy๋ ๋น์ฅ MethodAB()์ ๋ฌ๋ฆฐ ์ด๋ ธํ ์ด์ ์ ํ์ ํด์๋ง ์ด๋๋ฐ์ด์ค๋ฅผ ์ฝ์ ํ๋ค.
์ดํ์ methodA๋ methodB๋ฅผ ๋ง๋๋, ๊ทธ๊ฒ ์ ์ฉ ํธ๋์ญ์ ๋ถ๊ฐ ๊ธฐ๋ฅ์ด ํ๋ก์ ๋ด๋ถ์ ์๊ธฐ ๋๋ฌธ์, ํด๋น ๋งค์๋๋ค์ ํธ๋์ญ์ ์์ด ๋์ํ๊ณ , ๋ฐ์ดํฐ ์ ์ฅ์ ์คํจํ๋ค.
3. ํด๊ฒฐ ๋ฐฉ๋ฒ
์๋ก์ด beanProxy๋ฅผ ์์ฑํ๋ ์ ํ๊ณผ ๊ทธ๋ฌ์ง ์๋ ์ ํ์ผ๋ก ๋๋์ด ์ค๋ช
ํ ์ ์์ ๊ฒ ๊ฐ๋ค.
์์ ์์๋ฅผ ๊ฐ์ง๊ณ ์ฐจ๋ก๋ก ์ค๋ช
ํ๊ณ๋ค.
(1) ๋ด๋ถ ๋งค์๋๋ฅผ ๋ชจ๋ ๋ค๋ฅธ ํด๋์ค๋ก ๋นผ๊ธฐ
public class Test {
@AutoWired
Test2 test2;
@AutoWired
Test3 test3;
@Logging
public void methodAB(A a, B b) {
test2.methodA(A a);
test3.methodB(B b);
}
}
// ๋ค๋ฅธ ํ์ผ
public class Test2 {
@Transactional
public void methodA(A a) {
repository.save(A a);
}
}
// ๋ค๋ฅธ ํ์ผ
public class Test3 {
@Transactional
public void methodB(B b) {
repository.save(B b);
}
}
์์ ๊ฐ์ด ํ๋ฉด, methodAB์์ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋งค๋ฒ ๋ค์ ๋ถ๋ฅด๋ฏ๋ก, ๊ทธ๋ ๊ทธ๋๋ง๋ค ์๋ก์ด Proxy ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ๋ถ๊ฐ๊ธฐ๋ฅ์ ์ฒ๋ฆฌํ ์ ์๊ฒ ๋๋ค.
(2) SELF INJECTION
(์๊ฐ ์ฃผ์
)
(1)๋ฒ์ ๋ฐฉ๋ฒ์ ์๋ก์ด ํด๋์ค๋ก ๋ถ๋ฆฌํ์ง ์๊ณ ํ๋ ๋ฐฉ๋ฒ์ด๋ค. ์ฆ ๊ฐ์ฒด๊ฐ ์๊ธฐ ์์ ์ ๋ค์ ํธ์ถํ๊ณ , ๊ทธ ์์ ๋งค์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
public class Test {
@AutoWired
Test myself1;
@Autowired
Test myself2;
public void saveAB(A a, B b){
myself1.saveA(a);
myself2.saveB(b);
}
@Transactional
public void saveA(A a) {
// ์ค์ DB์ ์ ์ฅํ๋ ๋งค์๋
repository.save(A a);
}
@Transactoinoal
public void saveB(B b) {
// ์ค์ DB์ ์ ์ฅํ๋ ๋งค์๋
repository.save(B b);
}
}
์ด๋ ๊ฒ ํด๋ ์์ ๊ฐ์ด ๋งค๋ฒ ์๋ก์ด Proxy๊ฐ ์๋ํ์ฌ ๋ด๋ถ ๋งค์๋์ AOP๋ ์คํํ ์ ์๊ฒ ๋๋ค.
(3) ์ธ๋ถ ๋งค์๋์ ๋ด๋ถ ๋งค์๋๊ฐ ํ์ํ ๋ถ๊ฐ ๊ธฐ๋ฅ๊น์ง ๊ฐ์ด ์ค์
์ฃผ์
์ด๊ฑด ๋๋ ๊ฒฝ์ฐ์ ์ ๋๋ ๊ฒฝ์ฐ๊ฐ ๋๋ ์ ์๋ค.
@Transactional ์ด๋ ธํ ์ด์ ์ ๊ฒฝ์ฐ ์ธ๋ถ ๋งค์๋์ ํธ๋์ญ์ ์ปจํ ์คํธ๊ฐ ๋ด๋ถ ์ปจํ ์คํธ๋ฅผ ํจ๊ป ํฌํจํ ์ ์์ผ๋ฏ๋ก ๊ฐ๋ฅํ๋ค. @Cache๋ ๋ง์ฐฌ๊ฐ์ง์ด๋ค.
๋ฐ๋ฉด, ๋ด๋ถ ์งํ ์ํฉ์ ๋ํ Logging ์ด๋ ธํ ์ด์ ์ด๋ผ๋๊ฐ ๋งคํธ๋ฆญ ์์ง์ ๋ถ๊ฐ๋ฅ ํ ๊ฒ์ด๋ค.
public class Test {
@Transactional
public void saveAB(A a, B b){
saveA(a);
saveB(b);
}
@Transactional // ์ด์งํผ ์๋ ์ํจ ์ฆ ํ์์์
public void saveA(A a) {
// ์ค์ DB์ ์ ์ฅํ๋ ๋งค์๋
repository.save(A a);
}
@Transactoinoal // ์ฌ๊ธฐ๋ ๋ง์ฐฌ๊ฐ์ง
public void saveB(B b) {
// ์ค์ DB์ ์ ์ฅํ๋ ๋งค์๋
repository.save(B b);
}
}
์์ ๊ฐ์ด ์ ์ผ๋ฉด, ์ธ๋ถ ๋งค์๋ ํธ๋์ญ์
์ ๋ด๋ถ ๋งค์๋๊ฐ ์ ๋ถ ๋ฌถ์ด๊ฒ ๋๋ฏ๋ก Proxy ๊ฐ์ฒด๋ฅผ ์๋ก ์์ฑํ๋ ์ ์ฐจ ์์ด๋ ํด๊ฒฐ์ด ๊ฐ๋ฅํ๋ค. ํ์ง๋ง ์ด๋ ๋ชจ๋ AOP์ ๋ํด์ ์ ์ฉ๋๋ ๊ฒ์ ์๋๊ณ ์์ @Transactional
์ ๊ฒฝ์ฐ์ฒ๋ผ ์ธ๋ถ ๋งค์๋ AOP์ ๋ด๋ถ ๋งค์๋์ ์ค์ ์ ํฌํจ์์ผ๋ ์ ์ฒด ์ ์ฉ์ด ๊ฐ๋ฅํ ๊ฒฝ์ฐ ํ์ ์ด๋ค.
ํต์ฌ ์์ฝ
SELF INVOCATION
์ด๋ ํน์ ๋งค์๋ A๊ฐ ๊ฐ์ ๊ฐ์ฒด ๋ด์ ๋งค์๋ B๋ฅผ ์ง์ ํธ์ถํด์ ์ฌ์ฉํ๋ค๋ฉด, ๋งค์๋ B์ AOP๋ ๋ฌด์๋๋ AOP ๋งค์ปค๋์ฆ์ ๋ถ์์ฉ์ ๋งํ๋ค.- ํด๋น ์ผ์ด ๋ฒ์ด์ง๋ ์ด์ ๋ Spring์์ AOP๋ ๋์ ๊ฐ์ฒด ํธ์ถ์ Trigger ๋๊ธฐ ๋๋ฌธ์ด๋ค. ๋ด๋ถ ํธ์ถํ ๋งค์๋๋ค์ ๋์ ๊ฐ์ฒด ํธ์ถ์ด ์ด๋ฃจ์ด์ง์ง ์์, AOP๋ฅผ ์ํ ๋น ํ๋ก์๋ฅผ ํ์ฉํ ์ ์๋ค.
- ํด๊ฒฐ ๋ฐฉ๋ฒ์ผ๋ก๋ ๋ด๋ถ ๋งค์๋๋ฅผ ํ ํด๋์ค๋ก ๋ถ๋ฆฌ, ์๊ฐ ์ฃผ์ , ๊ฐ๋ฅํ ๊ฒฝ์ฐ์ ์ธ๋ถ ๋งค์๋์ ๋ด๋ถ ๋งค์๋ AOP ํฌํจ์ํค๊ธฐ ์ด๋ค.
Metadata
A. ๋ชจ๋ฅด๋ ๋จ์ด ์ ๋ฆฌ
B. ์ฐธ๊ณ ๋ฌธ์
- Spring ๊ณต์ ๋ฌธ์ - AOP์ ๋งค์ปค๋์ฆ
- StackOverFlow - Spring @Transactional Annotation : Self Invocation
C. ๊ด๋ จ ๊ธ
TABLE without id file.inlinks AS "BackLink"
WHERE file.path = this.file.path