public interface ItemService { public String getName(); // 추가된 abstract methods public String getAddr(); public int getAge();}
@Componentpublic class ItemServiceImpl implements ItemService { @Autowired private ItemDAO i_dao; @Override public String getName() { String name = "김정윤"; System.out.println("getName /// "+name); return name; } @Override public String getAddr() { String addr="서울시 강남구 역삼동"; System.out.println("getAddr /// "+ addr); return addr; } @Override public int getAge() { int age = 30; System.out.println("getAge /// "+age); return age; }}
@Aspect@Componentpublic class ItemAop { @Before("execution(* get*())") public void getter() { System.out.println("getter before advice"); }}
public class AopRun { public void execute() { ApplicationContext ac = new ClassPathXmlApplicationContext("kr/co/sist/run/application-context.xml"); ItemService is = ac.getBean(ItemService.class); is.getName(); is.getAddr(); is.getAge(); } public static void main(String[] args) { AopRun ar = new AopRun(); ar.execute(); }}
패키지명을 명시하면 한정시켜서 target을 줄 수 있다
@Before("execution(* kr.co.sist.service.get*())")
Pointcut으로 target method를 한정할 수 있다
execution의 대상은 @Component가 붙어있는 Spring Bean
// 모든 Bean의 getter 호출// @Before("execution(* get*())") // ItemServiceImpl의 getter 호출// @Before("execution(* kr.co.sist.service.ItemServiceImpl.get*())")// ItemServiceImpl의 반환형이 String인 getter 호출 @Before("execution(String kr.co.sist.service.ItemServiceImpl.get*())") public void getter() { System.out.println("getter before advice"); }
JoinPoint interface
JoinPoint는 @Before, @After, @AfterReturning, @AfterThrowing에서 사용되는 parameter를 Advice에서 처리하는 객체
Advice의 매개변수로 정의
@Before(...)public void test(JoinPoint jp) { Object[] objArr = jp.getArgs(); // target의 매개변수를 받아올 수 있다 Signature s = jp.getSignature(); String methodName = s.getName(); // target method의 method명 얻기 int modifier = s.getModifiers(); // target method의 접근지정자 얻기}
JoinPoint 사용 예
public class AopRun { public void execute() { ApplicationContext ac = new ClassPathXmlApplicationContext("kr/co/sist/run/application-context.xml"); ItemService is = ac.getBean(ItemService.class); ItemDomain id = is.searchItem("이재찬"); System.out.println(id.getItemNo()); System.out.println(id.getItem()); } public static void main(String[] args) { AopRun ar = new AopRun(); ar.execute(); }}
org.aspectj.lang.Signiture 를 사용하면 method정보(매개변수, method명)을 얻을 수 있다
@Around( ... )public 반환형 advice(ProceedingJoinPoint pjp) throws Throwable{ Object o = pjp.proceed(); // target method의 반환값을 가져옴 if (o instanceof String) { // 반환값이 특정 클래스인지 확인할 때는 instanceof로 비교 } return o;}
ProceedingJoinPoint 사용 예
public interface ItemService { public ItemDomain searchItem(String name); public ItemDomain searchData(String name);...
@Componentpublic class ItemServiceImpl implements ItemService {... @Override public ItemDomain searchData(String name) { return new ItemDomain("IO_O001", name+" 애벌레, 크런커.."); }}
@Aspect@Componentpublic class ItemAop { @Around("execution(* searchData(..))") // ".."은 모든 매개변수 public void around(ProceedingJoinPoint pjp) { }...
public class AopRun { public void execute() { ApplicationContext ac = new ClassPathXmlApplicationContext("kr/co/sist/run/application-context.xml"); ItemService is = ac.getBean(ItemService.class); ItemDomain id = is.searchData("정택성"); System.out.println(id.getItemNo()); System.out.println(id.getItem()); } public static void main(String[] args) { AopRun ar = new AopRun(); ar.execute(); }}
@Around("execution(* searchData(..))") // ".."은 모든 매개변수public ItemDomain around(ProceedingJoinPoint pjp) throws Throwable {// pjp.getArgs(); // target의 파라미터 처리가능// pjp.getSignature(); // target method 정보사용 // target의 리턴형을 받아와서 리턴을 만듦 ItemDomain id = (ItemDomain)pjp.proceed(); // target method가 유일할 때 if (id != null) { id.setItem(id.getItem()+"s('.^)V"); } return id;}/* @Around("execution(* searchData(..))") // ".."은 모든 매개변수 public Object around(ProceedingJoinPoint pjp) throws Throwable { // target의 리턴형을 받아와서 리턴을 만듦 Object o = pjp.proceed(); // target method가 여러개 일 때 return o; }*/