ð¡ AOPë êŽì ì§í¥ íë¡ê·žëë°(Aspect Oriented Programming)ì ìœììŽë€. ì€ë³µëë ê³µíµ ìœë륌 ë¶ëЬíê³ ìœë ì€í ì ìŽë íì ìì ì íŽë¹ ìœë륌 ìœì íšìŒë¡ìš ìì€ ìœëì ì€ë³µì ì€ìŽê³ , íìí ëë§ë€ ê°ì žë€ ìž ì ìê² ê°ì²Žííë êž°ì ì ë§íë€.

| ì©ìŽ | ì€ëª |
|---|---|
| Aspect | íµì¬ ë¹ìŠëì€ ë¡ì§ê³Œë ë³ëë¡ ìíëë í¡ëš êŽì¬ì¬ë¥Œ ë§íë€. |
| Advice | Aspectì êž°ë¥ ì첎륌 ë§íë€. |
| Join point | Adviceê° ì ì©ë ì ìë ìì¹ë¥Œ ë§íë€. |
| Pointcut | Join point ì€ìì Adviceê° ì ì©ë ê°ë¥ì±ìŽ ìë ë¶ë¶ì ì ë³í ê²ì ë§íë€. |
| Weaving | Advice륌 íµì¬ ë¹ìŠëì€ ë¡ì§ì ì ì©íë ê²ì ë§íë€. |

| ì¢ ë¥ | ì€ëª |
|---|---|
| Before | ëì ë©ìëê° ì€íëêž° ìŽì ì ì€íëë ìŽëë°ìŽì€ |
| After-returning | ëì ë©ìëê° ì ìì ìŒë¡ ì€íë ìŽíì ì€íëë ìŽëë°ìŽì€ |
| After-throwing | ììžê° ë°ìíì ë ì€íëë ìŽëë°ìŽì€ |
| After | ëì ë©ìëê° ì€íë ìŽíì(ì ì, ììž êŽê³ììŽ) ì€íëë ìŽëë°ìŽì€ |
| Around | ëì ë©ìë ì€í ì /íì ì ì©ëë ìŽëë°ìŽì€ |
ì€íë§ íë ììí¬ìì ì ê³µíë AOPë ë€ì곌 ê°ì í¹ì§ì ê°ì§ë€.
íë¡ì êž°ë°ì AOP 구í첎 : ëì ê°ì²Ž(Target Object)ì ëí íë¡ì륌 ë§ë€ìŽ ì ê³µíë©°, íê²ì ê°ìžë íë¡ìë ìë² Runtime ìì ìì±ëë€.
ë©ìë ì¡°ìž í¬ìžížë§ ì ê³µ : íµì¬êž°ë¥(ëì ê°ì²Ž)ì ë©ìëê° ížì¶ëë ë°íì ìì ìë§ ë¶ê°êž°ë¥(ìŽëë°ìŽì€)ì ì ì©í ì ìë€.

@AllArgsConstructor
@ToString
public class MemberDTO {
private Long id;
private String name;
}@Repository
public class MemberDAO {
private final Map<Long, MemberDTO> memberMap;
public MemberDAO(){
memberMap = new HashMap<>();
memberMap.put(1L, new MemberDTO(1L, "ì êŽì"));
memberMap.put(2L, new MemberDTO(2L, "íêžžë"));
}
public Map<Long, MemberDTO> selectMembers(){
return memberMap;
};
public MemberDTO selectMember(Long id) {
MemberDTO returnMember = memberMap.get(id);
if(returnMember == null) throw new RuntimeException("íŽë¹íë idì íììŽ ììµëë€.");
return returnMember;
}
}@Service
public class MemberService {
private final MemberDAO memberDAO;
public MemberService(MemberDAO memberDAO) {
this.memberDAO = memberDAO;
}
public Map<Long, MemberDTO> selectMembers(){
System.out.println("selectMembers ë©ìë ì€í");
return memberDAO.selectMembers();
}
public MemberDTO selectMember(Long id) {
System.out.println("selectMember ë©ìë ì€í");
return memberDAO.selectMember(id);
}
}public class Application {
public static void main(String[] args) {
ApplicationContext context
= new AnnotationConfigApplicationContext("com.ohgiraffers.section01.aop");
MemberService memberService = context.getBean("memberService", MemberService.class);
System.out.println("=============== selectMembers ===============");
System.out.println(memberService.selectMembers());
System.out.println("=============== selectMember ===============");
System.out.println(memberService.selectMember(3L));
}
}=============== selectMembers ===============
{1=MemberDTO(id=1, name=ì êŽì), 2=MemberDTO(id=2, name=íêžžë)}
=============== selectMember ===============
Exception in thread "main" java.lang.RuntimeException: íŽë¹íë idì íììŽ ììµëë€.
...ìëµaspectjweaver , aspectjrt ëŒìŽëžë¬ëŠ¬ê° ììŽìŒ AOP êž°ë¥ìŽ ëìí ì ììŒë¯ë¡ build.gradle.kts íìŒì ì¶ê°íë€.dependencies {
...ìëµ
implementation("org.aspectj:aspectjweaver:1.9.19")
implementation("org.aspectj:aspectjrt:1.9.19")
}
ContextConfiguration ë¹ ì€ì íìŒì ìì±íë€. aspectjì autoProxy ì¬ì©ì êŽí ì€ì ì íŽ ì£ŒìŽìŒ adviceê° ëìíë€. proxyTargetClass=true ì€ì ì cglib륌 ìŽì©í íë¡ì륌 ìì±íë ë°©ììžë°, Spring 3.2ë¶í° ì€íë§ íë ììí¬ì í¬íšëìŽ ë³ë ëŒìŽëžë¬ëЬ ì€ì ì íì§ ìê³ ì¬ì©í ì ìë€. ì±ë¥ 멎ìì ë ì°ìíë€. @Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ContextConfiguration {
}
LoggingAspect íŽëì€ë¥Œ ìì±íê³ ë¹ ì€ìºëì íµíŽ ë¹ ë±ë¡ì íë€.
@Aspect : ponitcut곌 advice륌 íëì íŽëì€ ëšìë¡ ì ìíêž° ìí ìŽë
ží
ìŽì
ìŽë€.
@Aspect
@Component
public class LoggingAspect {}
LoggingAspect íŽëì€ì í¬ìžíž ì»·ì ì ìíë€.
@Pointcut : ì¬ë¬ ì¡°ìž í¬ìžížë¥Œ ë§€ì¹íêž° ìíŽ ì§ì í ííì
@Pointcut("execution(* com.ohgiraffers.section01.aop.*Service.*(..))")
public void logPointcut() {}
execution ì€ëª
executionì AOPìì ê°ì¥ ë§ìŽ ì¬ì©ëë í¬ìžížì»· ííì ì€ íëìŽë€. execution ííìì ë©ìë ì€í ìì ì ìŒì¹íë ì¡°ìží¬ìžížë¥Œ ì ìíë ë° ì¬ì©ëë€. executionííìì Ʞ볞 구ì±ì ë€ì곌 ê°ë€.execution([ì ê·Œì íìíšíŽ] [늬íŽíì
íšíŽ] [íŽëì€ìŽëŠíšíŽ] [ë©ìëìŽëŠíšíŽ]([íëŒë¯ží°íì
íšíŽ])) com.example.* íší€ì§ ëŽì íŽëì€ìì ë°íê°ìŽ voidìž ë©ìë ì€, ë©ìëëª
ìŽ "get*"ìŒë¡ ììíë ë©ìë륌 í¬íšíë ííìì ë€ì곌 ê°ë€.execution(void com.example.*.*.get*(..))void : ëŠ¬íŽ íì
íšíŽìŒë¡ ë°íê°ìŽ voidìž ë©ìë륌 ëíëžë€.
com.example.*.* : íŽëì€ ìŽëŠ íšíŽìŒë¡ com.example íší€ì§ ëŽì 몚ë íŽëì€ë¥Œ ëíëžë€.
get* : ë©ìë ìŽëŠ íšíŽìŒë¡ "get"ìŒë¡ ììíë 몚ë ë©ìë륌 ëíëžë€.
.. : íëŒë¯ží° íì
íšíŽìŒë¡ 몚ë íëŒë¯ží°ë¥Œ ëíëžë€.
com.example íší€ì§ ëŽì íŽëì€ìì ë©ìëëª
ìŽ "set*"ìŒë¡ ììíë ë©ìë ì€, ìžìë¡ java.lang.String íì
ì ìžì륌 ê°ë ë©ìë륌 í¬íšíë ííìì ë€ì곌 ê°ë€.
execution(* com.example..set*(java.lang.String))
* : 늬íŽíì
íšíŽìŒë¡ 몚ë ë°íê°ì ëíëžë€.
com.example.. : íŽëì€ ìŽëŠ íšíŽìŒë¡ com.example íší€ì§ ëŽì 몚ë íŽëì€ë¥Œ ëíëžë€.
set* : ë©ìë ìŽëŠ íšíŽìŒë¡ "set"ìŒë¡ ììíë 몚ë ë©ìë륌 ëíëžë€.
java.lang.String : íëŒë¯ží° íì
íšíŽìŒë¡ ìžìë¡ java.lang.String íì
íëë§ì ëíëžë€.
Before ìŽëë°ìŽì€ë ëì ë©ìëê° ì€íëêž° ìŽì ì ì€íëë ìŽëë°ìŽì€ìŽë€. 믞늬 ìì±í í¬ìžíž ì»·ì ì€ì íë€.
JoinPointë í¬ìžížì»·ìŒë¡ íšì¹í ì€í ì§ì ìŽë€. ë§€ê°ë³ìë¡ ì ë¬í JoinPoint ê°ì²Žë íì¬ ì¡°ìž í¬ìžížì ë©ìëëª
, ìžìê° ë±ì ììží ì 볎륌 ììžì€ í ì ìë€.
@Before("LoggingAspect.logPointcut()")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Before joinPoint.getTarget() " + joinPoint.getTarget());
System.out.println("Before joinPoint.getSignature() " + joinPoint.getSignature());
if(joinPoint.getArgs().length > 0){
System.out.println("Before joinPoint.getArgs()[0] " + joinPoint.getArgs()[0]);
}
}
=============== selectMembers ===============
Before joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@6ed3f258
Before joinPoint.getSignature() Map com.ohgiraffers.section01.aop.MemberService.selectMembers()
selectMembers ë©ìë ì€í
{1=MemberDTO(id=1, name=ì êŽì), 2=MemberDTO(id=2, name=íêžžë)}
=============== selectMember ===============
Before joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@6ed3f258
Before joinPoint.getSignature()
MemberDTO com.ohgiraffers.section01.aop.MemberService.selectMember(Long)
Before joinPoint.getArgs()[0] 3
selectMember ë©ìë ì€í
Exception in thread "main" java.lang.RuntimeException: íŽë¹íë idì íììŽ ììµëë€.
...ìëµMemberService íŽëì€ì selectMembers ë©ìëì selectMember ë©ìëê° ì€í ëêž° ì Before ìŽëë°ìŽì€ì ì€í ëŽì©ìŽ ìœì
ëìŽ ëìíë ê²ì íìží ì ìë€.After ìŽëë°ìŽì€ë ëì ë©ìëê° ì€íë ìŽíì(ì ì, ììž êŽê³ììŽ) ì€íëë ìŽëë°ìŽì€ìŽë€. 믞늬 ìì±í í¬ìžíž ì»·ì ì€ì íë€. í¬ìžíž ì»·ì ëìŒí íŽëì€ ëŽìì ì¬ì©íë ê²ìŽë©Ž íŽëì€ëª
ì ìëµ ê°ë¥íë€. ëš, íší€ì§ê° ë€ë¥Žë©Ž íší€ì§ë¥Œ í¬íší íŽëì€ëª
ì êž°ì íŽìŒ íë€.
Before ìŽëë°ìŽì€ì ëìŒíê² ë§€ê°ë³ìë¡ JoinPoint ê°ì²Žë¥Œ ì ë¬ ë°ì ì ìë€.
@After("logPointcut()")
public void logAfter(JoinPoint joinPoint) {
System.out.println("After joinPoint.getTarget() " + joinPoint.getTarget());
System.out.println("After joinPoint.getSignature() " + joinPoint.getSignature());
if(joinPoint.getArgs().length > 0){
System.out.println("After joinPoint.getArgs()[0] " + joinPoint.getArgs()[0]);
}
}
=============== selectMembers ===============
Before joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@5443d039
Before joinPoint.getSignature() Map com.ohgiraffers.section01.aop.MemberService.selectMembers()
selectMembers ë©ìë ì€í
After joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@5443d039
After joinPoint.getSignature() Map com.ohgiraffers.section01.aop.MemberService.selectMembers()
{1=MemberDTO(id=1, name=ì êŽì), 2=MemberDTO(id=2, name=íêžžë)}
=============== selectMember ===============
Before joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@5443d039
Before joinPoint.getSignature()
MemberDTO com.ohgiraffers.section01.aop.MemberService.selectMember(Long)
Before joinPoint.getArgs()[0] 3
selectMember ë©ìë ì€í
After joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@5443d039
After joinPoint.getSignature()
MemberDTO com.ohgiraffers.section01.aop.MemberService.selectMember(Long)
After joinPoint.getArgs()[0] 3
Exception in thread "main" java.lang.RuntimeException: íŽë¹íë idì íììŽ ììµëë€.
...ìëµMemberService íŽëì€ì selectMembers ë©ìëì selectMember ë©ìëê° ì€í ë íì After ìŽëë°ìŽì€ì ì€í ëŽì©ìŽ ìœì
ëìŽ ëìíë ê²ì íìží ì ìë€. Exception ë°ì ì¬ë¶ì 묎êŽíê² íì ì€íëë€.AfterReturning ìŽëë°ìŽì€ë ëì ë©ìëê° ì ìì ìŒë¡ ì€íë ìŽíì ì€íëë ìŽëë°ìŽì€ìŽë€. 믞늬 ìì±í í¬ìžíž ì»·ì ì€ì íë€.
returning ìì±ì 늬íŽê°ìŒë¡ ë°ìì¬ ì€ëžì ížì ë§€ê°ë³ì ìŽëŠê³Œ ëìŒíŽìŒ íë€. ëí joinPointë ë°ëì 첫 ë²ì§ž ë§€ê°ë³ìë¡ ì ìžíŽìŒ íë€. ìŽ ìŽëë°ìŽì€ììë ë°í ê°ì ê°ê³µí ìë ìë€.
@AfterReturning(pointcut="logPointcut()", returning="result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("After Returning result " + result);
/* 늬íŽí 결곌ê°ì ë³ê²œíŽ ì€ ì ë ìë€. */
if(result != null && result instanceof Map) {
((Map<Long, MemberDTO>) result).put(100L, new MemberDTO(100L, "ë°í ê° ê°ê³µ"));
}
}
=============== selectMembers ===============
Before joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@2a62b5bc
Before joinPoint.getSignature() Map com.ohgiraffers.section01.aop.MemberService.selectMembers()
selectMembers ë©ìë ì€í
After Returning result {1=MemberDTO(id=1, name=ì êŽì), 2=MemberDTO(id=2, name=íêžžë)}
After joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@2a62b5bc
After joinPoint.getSignature() Map com.ohgiraffers.section01.aop.MemberService.selectMembers()
{1=MemberDTO(id=1, name=ì êŽì), 2=MemberDTO(id=2, name=íêžžë),
100=MemberDTO(id=100, name=ë°í ê° ê°ê³µ)}
=============== selectMember ===============
Before joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@2a62b5bc
Before joinPoint.getSignature()
MemberDTO com.ohgiraffers.section01.aop.MemberService.selectMember(Long)
Before joinPoint.getArgs()[0] 3
selectMember ë©ìë ì€í
After joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@2a62b5bc
After joinPoint.getSignature()
MemberDTO com.ohgiraffers.section01.aop.MemberService.selectMember(Long)
After joinPoint.getArgs()[0] 3
Exception in thread "main" java.lang.RuntimeException: íŽë¹íë idì íììŽ ììµëë€.
...ìëµMemberService íŽëì€ì selectMembers ë©ìëê° ì€í ë íì AfterReturning ìŽëë°ìŽì€ì ì€í ëŽì©ìŽ ìœì
ëìŽ ëìíë ê²ì íìží ì ìë€. Exception ìŽ ë°ìí selectMember ë©ìëììë ëìíì§ ìëë€.AfterThrowing ìŽëë°ìŽì€ë ììžê° ë°ìíì ë ì€íëë ìŽëë°ìŽì€ìŽë€. 믞늬 ìì±í í¬ìžíž ì»·ì ì€ì íë€.
throwing ìì±ì ìŽëŠê³Œ ë§€ê°ë³ìì ìŽëŠìŽ ëìŒíŽìŒ íë€. ìŽ ìŽëë°ìŽì€ììë Exception ì ë°ë¥ž ì²ëŠ¬ë¥Œ ìì±í ì ìë€.
@AfterThrowing(pointcut="logPointcut()", throwing="exception")
public void logAfterThrowing(Throwable exception) {
System.out.println("After Throwing exception " + exception);
}
=============== selectMembers ===============
Before joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@24111ef1
Before joinPoint.getSignature() Map com.ohgiraffers.section01.aop.MemberService.selectMembers()
selectMembers ë©ìë ì€í
After Returning result {1=MemberDTO(id=1, name=ì êŽì), 2=MemberDTO(id=2, name=íêžžë)}
After joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@24111ef1
After joinPoint.getSignature() Map com.ohgiraffers.section01.aop.MemberService.selectMembers()
{1=MemberDTO(id=1, name=ì êŽì), 2=MemberDTO(id=2, name=íêžžë),
100=MemberDTO(id=100, name=ë°í ê° ê°ê³µ)}
=============== selectMember ===============
Before joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@24111ef1
Before joinPoint.getSignature()
MemberDTO com.ohgiraffers.section01.aop.MemberService.selectMember(Long)
Before joinPoint.getArgs()[0] 3
selectMember ë©ìë ì€í
After Throwing exception java.lang.RuntimeException: íŽë¹íë idì íììŽ ììµëë€.
After joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@24111ef1
After joinPoint.getSignature()
MemberDTO com.ohgiraffers.section01.aop.MemberService.selectMember(Long)
After joinPoint.getArgs()[0] 3
Exception in thread "main" java.lang.RuntimeException: íŽë¹íë idì íììŽ ììµëë€.
...ìëµMemberService íŽëì€ì selectMember ë©ìëê° ì€í ë íì AfterThrowing ìŽëë°ìŽì€ì ì€í ëŽì©ìŽ ìœì
ëìŽ ëìíë ê²ì íìží ì ìë€. Exception ìŽ ë°ìíì§ ìì selectMembers ë©ìëììë ëìíì§ ìëë€.Around ìŽëë°ìŽì€ë ëì ë©ìë ì€í ì /íì ì ì©ëë ìŽëë°ìŽì€ìŽë€. 믞늬 ìì±í í¬ìžíž ì»·ì ì€ì íë€.
Around Adviceë ê°ì¥ ê°ë ¥í ìŽëë°ìŽì€ìŽë€. ìŽ ìŽëë°ìŽì€ë ì¡°ìží¬ìžížë¥Œ ìì í ì¥ì íêž° ë묞ì ìì ìŽíŽ ë³ž ìŽëë°ìŽì€ 몚ë Around ìŽëë°ìŽì€ë¡ ì¡°í©í ì ìë€.
AroundAdviceì ì¡°ìží¬ìžíž ë§€ê°ë³ìë ProceedingJoinPointë¡ ê³ ì ëìŽ ìë€. JoinPointì íì ìží°íìŽì€ë¡ ì볞 ì¡°ìží¬ìžížì ì§í ìì ì ì ìŽí ì ìë€.
ì¡°ìží¬ìžíž ì§ííë ížì¶ì ìë 겜ì°ê° ì죌 ë°ìíêž° ë묞ì 죌ìíŽìŒ íë©° ìµìíì ì걎ì 충족í멎ìë ê°ì¥ êž°ë¥ìŽ ìœí ìŽëë°ìŽì€ë¥Œ ì°ëê² ë°ëì§íë€.
@Around("logPointcut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Around Before " + joinPoint.getSignature().getName());
/* ì볞 ì¡°ìží¬ìžížë¥Œ ì€ííë€. */
Object result = joinPoint.proceed();
System.out.println("Around After " + joinPoint.getSignature().getName());
/* ì볞 ì¡°ìží¬ìžížë¥Œ ížì¶í 쪜 í¹ì ë€ë¥ž ìŽëë°ìŽì€ê° ë€ì ì€íí ì ìëë¡ ë°ííë€. */
return result;
}
=============== selectMembers ===============
Around Before selectMembers
Before joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@21a21c64
Before joinPoint.getSignature() Map com.ohgiraffers.section01.aop.MemberService.selectMembers()
selectMembers ë©ìë ì€í
After Returning result {1=MemberDTO(id=1, name=ì êŽì), 2=MemberDTO(id=2, name=íêžžë)}
After joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@21a21c64
After joinPoint.getSignature() Map com.ohgiraffers.section01.aop.MemberService.selectMembers()
Around After selectMembers
{1=MemberDTO(id=1, name=ì êŽì), 2=MemberDTO(id=2, name=íêžžë),
100=MemberDTO(id=100, name=ë°í ê° ê°ê³µ)}
=============== selectMember ===============
Around Before selectMember
Before joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@21a21c64
Before joinPoint.getSignature()
MemberDTO com.ohgiraffers.section01.aop.MemberService.selectMember(Long)
Before joinPoint.getArgs()[0] 3
selectMember ë©ìë ì€í
After Throwing exception java.lang.RuntimeException: íŽë¹íë idì íììŽ ììµëë€.
After joinPoint.getTarget() com.ohgiraffers.section01.aop.MemberService@21a21c64
After joinPoint.getSignature()
MemberDTO com.ohgiraffers.section01.aop.MemberService.selectMember(Long)
After joinPoint.getArgs()[0] 3
Exception in thread "main" java.lang.RuntimeException: íŽë¹íë idì íììŽ ììµëë€.
...ìëµMemberService íŽëì€ì selectMember ë©ìëê° ì€í ë íì AfterThrowing ìŽëë°ìŽì€ì ì€í ëŽì©ìŽ ìœì
ëìŽ ëìíë ê²ì íìží ì ìë€. Exception ìŽ ë°ìíì§ ìì selectMembers ë©ìëììë ëìíì§ ìëë€.ð¡ ìë° ëŠ¬íë ì (Reflection)ì ì€í ì€ìž ìë° íë¡ê·žëš ëŽë¶ì íŽëì€, ë©ìë, íë ë±ì ì 볎륌 ë¶ìíì¬ ë€ë£šë êž°ë²ì ë§íë€. ìŽë¥Œ íµíŽ íë¡ê·žëšì ëì ìž í¹ì±ì 구íí ì ìë€. ì륌 ë€ìŽ, 늬íë ì ì ìŽì©í멎 ì€í ì€ìž ê°ì²Žì íŽëì€ ì 볎륌 ì»ìŽì€ê±°ë, íŽëì€ ëŽë¶ì íëë ë©ìëì ì ê·Œí ì ìë€. ìŽë¬í êž°ë¥ë€ì íë ììí¬, ëŒìŽëžë¬ëЬ, í ì€íž ìœë ë±ìì ì ì©íê² íì©ëë€.
â ì€íë§ììë Reflectionì ì¬ì©íŽì ë°íì ì ë±ë¡í ë¹ì ì í늬ìŒìŽì
ëŽìì ì¬ì©í ì ìê² íë€.
Account íŽëì€ë¥Œ ìì±íë€.public class Account {
private String backCode;
private String accNo;
private String accPwd;
private int balance;
public Account() {}
public Account(String bankCode, String accNo, String accPwd) {
this.backCode = bankCode;
this.accNo = accNo;
this.accPwd = accPwd;
}
public Account(String bankCode, String accNo, String accPwd, int balance) {
this(bankCode, accNo, accPwd);
this.balance = balance;
}
/* íì¬ ìì¡ì ì¶ë ¥íŽì£Œë ë©ìë */
public String getBalance() {
return this.accNo + " ê³ì¢ì íì¬ ìì¡ì " + this.balance + "ì ì
ëë€.";
}
/* êžì¡ì ë§€ê°ë³ìë¡ ì ë¬ ë°ì ìì¡ì ìŠê°(ì
êž) ììŒì£Œë ë©ìë */
public String deposit(int money) {
String str = "";
if(money >= 0) {
this.balance += money;
str = money + "ììŽ ì
êžëììµëë€.";
}else {
str = "êžì¡ì ì못 ì
ë ¥íì
šìµëë€.";
}
return str;
}
/* êžì¡ì ë§€ê°ë³ìë¡ ë°ì ìì¡ì ê°ì(ì¶êž) ììŒì£Œë ë©ìë */
public String withDraw(int money) {
String str = "";
if(this.balance >= money) {
this.balance -= money;
str = money + "ììŽ ì¶êžëììµëë€.";
}else {
str = "ìì¡ìŽ ë¶ì¡±í©ëë€. ìì¡ì íìžíŽì£Œìžì.";
}
return str;
}
}
/* .class 묞ë²ì ìŽì©íì¬ Class íì
ì ìžì€íŽì€ë¥Œ ìì±í ì ìë€. */
Class class1 = Account.class;
System.out.println("class1 : " + class1);
/* Object íŽëì€ì getClass() ë©ìë륌 ìŽì©í멎 Class íì
ìŒë¡ 늬íŽë°ì ìŽì©í ì ìë€. */
Class class2 = new Account().getClass();
System.out.println("class2 : " + class2);
/* Class.forName() ë©ìë륌 ìŽì©íì¬ ë°íìì ë¡ë©ì íê³ ê·ž íŽëì€ ë©íì 볎륌 Class íì
ìŒë¡ ë°íë°ì ì ìë€. */
try {
Class class3 = Class.forName("com.ohgiraffers.section02.reflection.Account");
System.out.println("class3 : " + class3);
/* Doubleìë£í ë°°ìŽì ë¡ëí ì ìë€. */
Class class4 = Class.forName("[D");
Class class5 = double[].class;
System.out.println("class4 : " + class4);
System.out.println("class5 : " + class5);
/* Stringìë£í ë°°ìŽì ë¡ëí ì ìë€. */
Class class6 = Class.forName("[Ljava.lang.String;");
Class class7 = String[].class;
System.out.println("class6 : " + class6);
System.out.println("class7 : " + class7);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
/* ìì ìë£íì ì¬ì©í멎 컎íìŒ ìë¬ ë°ì */
// double d = 1.0;
// Class class8 = d.getClass();
/* TYPE íë륌 ìŽì©íì¬ ììí íŽëì€ë¥Œ ë°íë°ì ì ìë€. */
Class class8 = Double.TYPE;
System.out.println("class8 : " + class8);
Class class9 = Void.TYPE;
System.out.println("class9 : " + class9);
/* íŽëì€ì ë©í ì 볎륌 ìŽì©íì¬ ì¬ë¬ ê°ì§ ì 볎륌 ë°íë°ë ë©ìë륌 ì ê³µíë€. */
/* ììë ë¶ëªš íŽëì€ë¥Œ ë°ííë€. */
Class superClass = class1.getSuperclass();
System.out.println("superClass : " + superClass);
class1 : class com.ohgiraffers.section02.reflection.Account
class2 : class com.ohgiraffers.section02.reflection.Account
class3 : class com.ohgiraffers.section02.reflection.Account
class4 : class [D
class5 : class [D
class6 : class [Ljava.lang.String;
class7 : class [Ljava.lang.String;
class8 : double
class9 : void
superClass : class java.lang.ObjectField[] fields = Account.class.getDeclaredFields();
for(Field field : fields) {
System.out.println("modifiers : " + Modifier.toString(field.getModifiers()) +
", type : " + field.getType() +
", name : " + field.getName() );
}
modifiers : private, type : class java.lang.String, name : backCode
modifiers : private, type : class java.lang.String, name : accNo
modifiers : private, type : class java.lang.String, name : accPwd
modifiers : private, type : int, name : balanceConstructor[] constructors = Account.class.getConstructors();
for(Constructor con : constructors) {
System.out.println("name : " + con.getName());
Class[] params = con.getParameterTypes();
for(Class param : params) {
System.out.println("paramType : " + param.getTypeName());
}
}
name : com.ohgiraffers.section02.reflection.Account
paramType : java.lang.String
paramType : java.lang.String
paramType : java.lang.String
paramType : int
name : com.ohgiraffers.section02.reflection.Account
paramType : java.lang.String
paramType : java.lang.String
paramType : java.lang.String
name : com.ohgiraffers.section02.reflection.Accounttry {
Account acc = (Account) constructors[0].newInstance("20", "110-223-123456", "1234", 10000);
System.out.println(acc.getBalance());
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
110-223-123456 ê³ì¢ì íì¬ ìì¡ì 10000ì ì
ëë€.Method[] methods = Account.class.getMethods();
Method getBalanceMethod = null;
for(Method method : methods) {
System.out.println(Modifier.toString(method.getModifiers()) + " " +
method.getReturnType().getSimpleName() + " " +
method.getName());
if("getBalance".equals(method.getName())) {
getBalanceMethod = method;
}
}
public String getBalance
public String withDraw
public String deposit
public final native void wait
public final void wait
public final void wait
public boolean equals
public String toString
public native int hashCode
public final native Class getClass
public final native void notify
public final native void notifyAlltry {
System.out.println(getBalanceMethod.invoke(((Account) constructors[2].newInstance())));
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
null ê³ì¢ì íì¬ ìì¡ì 0ì ì
ëë€.ð¡ Javaìì íë¡ì(Proxy)ë ë늬ì륌 ì믞íë€. íë¡ìë Ʞ졎ì ê°ì²Žë¥Œ ê°ìžì ê·ž ê°ì²Žì êž°ë¥ì íì¥íê±°ë ë³ê²œí ì ìê² íŽì€ë€. ì륌 ë€ìŽ, íë¡ì ê°ì²Žë¥Œ ì¬ì©í멎 ê°ì²Žì ëí ì ê·Œì ì ìŽíê±°ë, ê°ì²Žì ë©ìë ížì¶ ì íì ë¡ê¹ ìì ë±ì ìíí ì ìë€. ëí, íë¡ì ê°ì²Žë¥Œ ì¬ì©íì¬ ì격ìŒë¡ ì€íëë ê°ì²Žë¥Œ ížì¶í ìë ìë€. íë¡ìë ì£Œë¡ AOP(Aspect Oriented Programming)ìì ì¬ì©ëë€.
íë¡ì ìì±ì í¬ê² ë ê°ì§ ë°©ììŽ ì ê³µëë€.
JDK Dynamic Proxy ë°©ì
CGLib ë°©ì
ëì ìŒë¡ Proxy륌 ìì±íì§ë§ ë°ìŽížìœë륌 ì¡°ìíì¬ íë¡ì륌 ìì±íŽì£Œë ë°©ììŽë€. ìží°íìŽì€ ë¿ ìëëŒ íê²ì íŽëì€ê° ìží°íìŽì€ë¥Œ 구ííì§ ììë íë¡ì륌 ìì±íŽì€ë€. CGLib(Code Generator Library)ì 겜ì°ìë ì²ì ë©ìëê° ížì¶ë ë¹ì ëì ìŒë¡ íìŒ íŽëì€ì ë°ìŽíž ìœë륌 ì¡°ìíê² ëê³ , ê·ž ìŽí ížì¶ ìë¶í°ë ë³ê²œë ìœë륌 ì¬ì¬ì©íë€. ë°ëŒì ë§€ë² ê²ìŠ ìœë륌 ê±°ì¹ë 1ë² ë°©ì볎ë€ë invokeì ë ë¹ ë¥Žê² ëë€. ëí 늬íë ì ì ìí ê²ìŽ ìë ë°ìŽížìœë륌 ì¡°ìíë ë°©ììŽêž° ë묞ì ì±ë¥ë©Žììë ë ì°ìíë€.
íì§ë§ CGLib ë°©ìì ì€íë§ìì Ʞ볞ì ìŒë¡ ì ê³µëë ë°©ìì ìëìêž°ì ë³ëë¡ ì졎ì±ì ì¶ê°íì¬ ê°ë°íŽìŒ íê³ , íëŒë¯ží°ê° ìë default ìì±ìê° ë°ëì íìíìŒë©°, ìì±ë íë¡ìì ë©ìë륌 ížì¶í멎 íê²ì ìì±ìê° 2ë² ížì¶ëë ë±ì 묞ì ì ë€ìŽ ììë€.
ì€íë§ 4.3, ì€íë§ë¶íž 1.3 ìŽíë¶í° CGLibì 묞ì ê° ë ë¶ë¶ìŽ ê°ì ëìŽ êž°ë³ž core íší€ì§ì í¬íšëê² ëìê³ , ì€íë§ìì Ʞ볞ì ìŒë¡ ì¬ì©íë íë¡ì ë°©ììŽ CGLib ë°©ììŽ ëìë€.
public interface Student {
void study(int hours);
}
public class OhgiraffersStudent implements Student {
@Override
public void study(int hours) {
System.out.println(hours + "ìê° ëì ìŽì¬í ê³µë¶í©ëë€.");
}
}
java.lang.reflect.InvocationHandler륌 구íí íŽëì€ë¥Œ ìì±íë€.
Student íŽëì€ë¥Œ íê² ìžì€íŽì€ë¡ ì€ì íê³ invoke ë©ìë륌 ì ìíë€.
public class Handler implements InvocationHandler {
/* ë©ìë ížì¶ì ìíŽ íê² ìžì€íŽì€ê° íìíë€ */
private final Student student;
public Handler(Student student) {
this.student = student;
}
/* ìì±ë proxy ìžì€íŽì€ì íê² ë©ìë, ì ë¬ë°ì ìžì륌 ë§€ê°ë³ìë¡ íë€. */
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
System.out.println("============ ê³µë¶ê° ë묎 íê³ ì¶ìµëë€. ==============");
System.out.println("ížì¶ ëì ë©ìë : " + method);
for(Object arg : args) {
System.out.println("ì ë¬ë ìžì : " + arg);
}
/* íìŒ ë©ìë륌 ížì¶íë€. íê² Objectì ìžì륌 ë§€ê°ë³ìë¡ ì ë¬íë€.
* ì¬êž°ì íë¡ì륌 ì ë¬í멎 ë€ì íê²ì ížì¶í ë ë€ì íë¡ì륌 ìì±íê³ ë€ì ë ì ë¬íë 묎í 룚íì ë¹ ì§ê² ëë€.
* */
method.invoke(student, args);
System.out.println("============ ê³µë¶ë¥Œ ë§ì¹ê³ ì멎 íìµì ììí©ëë€. ============");
return proxy;
}
}
Student student = new OhgiraffersStudent();
Handler handler = new Handler(student);
/* íŽëì€ë¡ë, íë¡ì륌 ë§ë€ íŽëì€ ë©í ì 볎(ìží°íìŽì€ë§ ê°ë¥), íë¡ì ëìí ë ì ì©ë ížë€ë¬ */
Student proxy
= (Student) Proxy.newProxyInstance(Student.class.getClassLoader(), new Class[] {Student.class}, handler);
/* íë¡ìë¡ ê°ìžì§ ìžì€íŽì€ì ë©ìë륌 ížì¶íê² ë멎 ížë€ë¬ì ì ìí ë©ìëê° ížì¶ëë€. */
proxy.study(16);
============ ê³µë¶ê° ë묎 íê³ ì¶ìµëë€. ==============
ížì¶ ëì ë©ìë : public abstract void com.ohgiraffers.section03.proxy.common.Student.study(int)
ì ë¬ë ìžì : 16
16ìê° ëì ìŽì¬í ê³µë¶í©ëë€.
============ ê³µë¶ë¥Œ ë§ì¹ê³ ì멎 íìµì ììí©ëë€. ============study ë©ìë ížì¶ ì proxy ê°ì²Žì ëìì íìží ì ìë€.org.springframework.cglib.proxy.InvocationHandler륌 구íí íŽëì€ë¥Œ ìì±íë€.
OhgiraffersStudent íŽëì€ë¥Œ íê² ìžì€íŽì€ë¡ ì€ì íê³ invoke ë©ìë륌 ì ìíë€.
public class Handler implements InvocationHandler {
private final OhgiraffersStudent student;
public Handler(OhgiraffersStudent student) {
this.student = student;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
System.out.println("============ ê³µë¶ê° ë묎 íê³ ì¶ìµëë€. ==============");
System.out.println("ížì¶ ëì ë©ìë : " + method);
for(Object arg : args) {
System.out.println("ì ë¬ë ìžì : " + arg);
}
method.invoke(student, args);
System.out.println("============ ê³µë¶ë¥Œ ë§ì¹ê³ ì멎 íìµì ììí©ëë€. ============");
return proxy;
}
}
OhgiraffersStudent student = new OhgiraffersStudent();
Handler handler = new Handler(student);
/* Enhancer íŽëì€ì create static ë©ìëë íê² íŽëì€ì ë©íì 볎ì ížë€ë¬ë¥Œ ì ë¬í멎 proxy륌 ìì±íŽì ë°ííŽì€ë€. */
OhgiraffersStudent proxy
= (OhgiraffersStudent) Enhancer.create(OhgiraffersStudent.class, new Handler(new OhgiraffersStudent()));
proxy.study(20);
============ ê³µë¶ê° ë묎 íê³ ì¶ìµëë€. ==============
ížì¶ ëì ë©ìë : public void com.ohgiraffers.section03.proxy.common.OhgiraffersStudent.study(int)
ì ë¬ë ìžì : 20
20ìê° ëì ìŽì¬í ê³µë¶í©ëë€.
============ ê³µë¶ë¥Œ ë§ì¹ê³ ì멎 íìµì ììí©ëë€. ============study ë©ìë ížì¶ ì proxy ê°ì²Žì ëìì íìží ì ìë€.