理解 AOP 通知和切点表达式参阅:
《Spring AOP通知(Advice)详解》
《Spring AOP切点表达式(Pointcut)详解》
Spring 项目定义 AOP 功能包含三个部分:切面、切点和通知。
Spring 定义的切点可以复用,可以作用于多个不同的通知。
Pointcut
是核心接口,通过实现它来定义切点。
package org.springframework.aop;
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
Pointcut
包含两部分,ClassFilter
用于指定目标类,MethodMatcher
匹配目标类中的方法。
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* cn.codeartist.spring.*.*(..))");
一般情况下我们不会去自定义切点,而是使用 Spring 提供的实现,例如上面基于 AspectJ 表达式的切点实现。
Spring 有五种通知类型,只讲下面四种通知类型的 API,通知的执行节点如下。
环绕通知最具功能性,通过实现 MethodInterceptor
接口来定义。
package org.aopalliance.intercept;
@FunctionalInterface
public interface MethodInterceptor extends Interceptor {
Object invoke(MethodInvocation invocation) throws Throwable;
}
代码示例如下,通过 invocation.proceed();
方法来调用实际方法或下一个环绕通知。
public class DemoAroundAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// do something before
Object proceed = invocation.proceed();
// do something after
return proceed;
}
}
环绕通知简单来讲,就是使用拦截器模式来对目标类中的方法进行拦截。
前置通知通过实现 MethodBeforeAdvice
来定义。
package org.springframework.aop;
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method method, Object[] args, @Nullable Object target) throws Throwable;
}
代码示例如下:
public class DemoBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
// do something before
}
}
前置通知中,可以获取到目标类,目标类的方法,以及方法的参数。
异常通知通过实现 ThrowsAdvice
来定义。
package org.springframework.aop;
public interface ThrowsAdvice extends AfterAdvice {
}
异常通知没有固定的接口方法,可以定义任何符合规范的方法。
// 方法签名模板
void afterThrowing([Method, args, target], ThrowableSubclass);
// 示例方法
public void afterThrowing(Exception ex);
public void afterThrowing(RemoteException);
public void afterThrowing(Method method, Object[] args, Object target, Exception ex);
public void afterThrowing(Method method, Object[] args, Object target, ServletException ex);
方法签名中的前三个参数(方法,参数,目标类)是可选的,第四个参数是异常类型(Throwable
的子类)。
通过第四个参数来匹配异常类型,只有当方法抛出该异常类型时通知才会被执行。
代码示例如下:
public class DemoThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(Method method, Object[] args, Object target, Exception ex) {
// do something after throwing
}
}
后置通知通过实现 AfterReturningAdvice
来定义。
package org.springframework.aop;
public interface AfterReturningAdvice extends AfterAdvice {
void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
}
代码示例如下:
public class DemoAfterReturningAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) {
// do something after returning
}
}
后置通知可以获取到方法执行成功后的返回值,但不能修改,方法抛出异常时不会执行。
Spring 中的通知者(Advisor)可以定义一个包含切点和通知的切面。
Advisor
和 PointcutAdvisor
是核心接口,用于定义通知者。
public interface Advisor {
Advice getAdvice();
}
public interface PointcutAdvisor extends Advisor {
Pointcut getPointcut();
}
PointcutAdvisor
接口实现需要指定切点和通知。
import org.springframework.aop.support.DefaultPointcutAdvisor;
@Bean
public Advisor demoPointcutAdvisor() {
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
advisor.setPointcut(pointcut);
advisor.setAdvice(advice);
return advisor;
}
一般情况下不用自定义通知者,而是用 Spring 提供的实现,例如上面的 DefaultPointcutAdvisor
类。
接口 | 描述 |
---|---|
Pointcut |
定义切点 |
MethodInterceptor |
定义环绕通知 |
MethodBeforeAdvice |
定义前置通知 |
ThrowsAdvice |
定义异常通知 |
AfterReturningAdvice |
定义后置通知 |
PointcutAdvisor |
定义通知者(切面) |
Gitee 仓库:https://gitee.com/code_artist/spring
更多文章关注码匠公众号:CodeArtist。