使用proxy指定劫持的class和需要的advise或者advisor
advise是用來指定需要插入的內容和位置
advisor傳入advise用來指定method
advise有四種形式
before: MethodBeforeAdvice 在方法調用前
public class HijackBeforeMethod implements MethodBeforeAdvice {
public void before(Method arg0, Object[] args, Object target)
throws Throwable {
System.out.println("HijackBeforeMethod : Before method hijacked!");
}
}
afterreturning:AfterReturningAdvice 在方法返回後
public class HijackAfterMethod implements AfterReturningAdvice {
public void afterReturning(Object returnValue, Method method, Object[] args,
Object target) throws Throwable {
System.out.println("HijackAfterMethod : After method hijacked!");
}
}
after-throwing:ThrowsAdvice 拋出異常時
public class HijackThrowExceptionMethod implements ThrowsAdvice {
public void afterThrowing(IllegalArgumentException e) throws Throwable {
System.out.println("HijackThrowException : Throw exception hijacked!");
}
}
around:MethodInterceptor 可以在實現這個藉口的類裏面同時實現上面三個功能
public class HijackAroundMethod implements MethodInterceptor {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("Method name : "
+ methodInvocation.getMethod().getName());
System.out.println("Method arguments : "
+ Arrays.toString(methodInvocation.getArguments()));
// 相當於 MethodBeforeAdvice
System.out.println("HijackAroundMethod : Before method hijacked!");
try {
// 調用原方法,即調用CustomerService中的方法
Object result = methodInvocation.proceed();
// 相當於 AfterReturningAdvice
System.out.println("HijackAroundMethod : After method hijacked!");
return result;
} catch (IllegalArgumentException e) {
// 相當於 ThrowsAdvice
System.out.println("HijackAroundMethod : Throw exception hijacked!");
throw e;
}
}
}
xml文檔
<bean id="hijackBeforeMethodBean" class="com.shiyanlou.spring.aop.advice.HijackBeforeMethod" />
<bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-指定需要劫持的class->
<property name="target" ref="customerService" />
<!--指定advise-->
<property name="interceptorNames">
<list>
<value>hijackAroundMethodBean</value>
</list>
</property>
</bean>
最後從context中獲得的bean是代理器而不是劫持的class本身
public class App {
public static void main(String[] args) {
ApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[] { "SpringAOPAdvice.xml" });
CustomerService cust = (CustomerService) appContext.getBean("customerServiceProxy");
System.out.println("*************************");
cust.printName();
System.out.println("*************************");
cust.printURL();
System.out.println("*************************");
try {
cust.printThrowException();
} catch (Exception e) {
}
}
}
註解實現aspectj
@Aspect
public class LoggingAspect {
//*表示任意的返回類型,後面是指定的class和method。(..)指任意的參數,class和method可以用*來表示任意class或者method
@Before("execution(public * com.shiyanlou.spring.aop.aspectj.CustomerBo.addCustomer(..))")
public void logBefore(JoinPoint joinPoint){
System.out.println("logBefore() is running ...");
System.out.println("hijacked:"+joinPoint.getSignature().getName());
System.out.println("**********");
}
@After("execution(public * com.shiyanlou.spring.aop.aspectj.CustomerBo.deleteCustomer(..))")
public void logAfter(JoinPoint joinPoint){
System.out.println("logAfter() is running ...");
System.out.println("hijacked:"+joinPoint.getSignature().getName());
System.out.println("**********");
}
}
以上是同時實現了pointcut和advise
@Aspect
public class PointcutDefine {
//指定了pointcut。方法 customerLog 是一個簽名,在 Advice 中可以用此簽名代替切入點表達式,所以不需要在方法體內編寫實際代碼,只起到助記功能
@Pointcut("execution(* test.CustomerBo.*(..))")
public void customerLog(){
}
}
@Aspect
public class LoggingAspect {
//通過簽名來找到pointcut然後寫advise
@Before("test.PointcutDefine.customerLog()")
public void logBefore(JoinPoint joinPoint){
System.out.println("logBefore() is running ...");
System.out.println("hijacked:"+joinPoint.getSignature().getName());
System.out.println("**********");
}
@After("test.PointcutDefine.customerLog()")
public void logAfter(JoinPoint joinPoint){
System.out.println("logAfter() is running ...");
System.out.println("hijacked:"+joinPoint.getSignature().getName());
System.out.println("**********");
}
}
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:util="http://www.springframework.org/schema/util"
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.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<aop:aspectj-autoproxy/>
<bean id="customerBo" class="test.CustomerBo"/>
<bean id="loggingAspect" class="test.LoggingAspect"/>
<beans>