- 第一种
通过实现接口实现
通知类型 | 需要实现的接口 |
---|---|
前置通知 | org.springframework.aop.MethodBeforeAdvice |
后置通知 | org.springframework.aop.AfterReturningAdvice |
异常通知 | org.springframework.aop.ThrowsAdvice |
环绕通知 | org.aopalliance.intercept.MethodInterceptor |
- 前置通知的接口实现
@Slf4j
public class LogBefore implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
//Method是切入点方法
//args是切入点方法参数
//target是调用切入点方法的对象
}
}
- 后置通知的接口实现
public class LogAfter implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
//returnValue是切入点方法返回值
//Method是切入点方法
//args是切入点方法参数
//target是调用切入点方法的对象
}
}
- 异常通知
异常通知的接口是一个空接口,没有定义方法,需要自己定义方法;
有两种方法实现方式,下面是其中一种
@Slf4j
public class LogException implements ThrowsAdvice {
public void afterThrowing(Throwable subclass) {
log.debug("{}", subclass.getMessage());
}
}
public void afterThrowing([Method, args, target], ThrowableSubclass)
中括号内为可选(必须同时存在或三个都没有),参数作用与前置通知相同,最后一个参数是异常类型,可以指定异常类型
- 环绕通知
public class LogSurround implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object target=null;
try {
log.debug("环绕通知前");
target = invocation.proceed();//返回结果
log.debug("环绕通知后");
}catch (Exception e){
log.debug("异常通知");
}finally{
log.debug("最终通知")
}
return target;
}
}
- 配置xml:
<bean class="com.hjf.student.aop.useXML.LogBefore" id="logBefore"/>
<bean class="com.hjf.student.aop.useXML.LogAfter" id="logAfter"/>
<bean class="com.hjf.student.aop.useXML.LogException" id="logException"/>
<bean class="com.hjf.student.aop.useXML.LogSurround" id="logSurround"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(public com.hjf.student.entity.Card getCardById(String))"/>
<aop:advisor advice-ref="logBefore" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logAfter" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logException" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logSurround" pointcut-ref="pointcut"/>
</aop:config>
- 基于aspectj实现
不需要实现接口
@Slf4j
public class LogAspectJ {
public void before(JoinPoint joinPoint) {
log.debug("AOP 前置通知");
}
//returnValue需要对应xml配置
public void afterReturning(JoinPoint joinPoint, Object returnValue) {
log.debug("AOP 后置通知");
}
public void after(JoinPoint joinPoint) {
log.debug("AOP 最终通知");
}
//通过第二个参数可以获取异常信息,可以指定异常类型
public void afterThrowing(JoinPoint joinPoint, Exception exception) {
log.debug("AOP 异常通知");
}
//ProceedingJoinPoint 是 JoinPoint的子类
public Object around(ProceedingJoinPoint pjp) {
Object target=null;
try {
log.debug("AOP around 前置通知");
target = pjp.proceed();
log.debug("AOP around 后置通知");
} catch (Throwable throwable) {
log.debug("AOP around 异常通知");
throwable.printStackTrace();
} finally {
log.debug("AOP around 最终通知");
}
return target;
}
}
JointPoint类可以获取切入点方法的信息,比如调用切入点方法的对象、参数个数等
xml配置:
<aop:config>
<aop:pointcut id="poincut" expression="execution(public com.hjf.student.entity.Card getCardById(String))"/>
<aop:aspect ref="logAOP">
<aop:before method="before" pointcut-ref="poincut"/>
<aop:after method="after" pointcut-ref="poincut"/>
<!--指定返回参数: returning="returnValue"-->
<aop:after-returning method="afterReturning" pointcut-ref="poincut" returning="returnValue"/>
<!--指定异常参数: throwing="exception"-->
<aop:after-throwing method="afterThrowing" pointcut-ref="poincut" throwing="exception"/>
<aop:around method="around" pointcut-ref="poincut"/>
</aop:aspect>
</aop:config>