使用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>