概念
通知类是spring面向切面编程的产物,其原理是动态代理的设计模式,动态代理设计模式不在此处展开讲。我们只需要知道到我们编写的advice类可以通过动态代理在其方法内部任意位置调用其它类的功能(也就是我们要增强的类)。所谓的前置后置其实就是增强代码在核心代码之前还是之后执行。
前置通知:MethodBeforeAdvice
对于前置通知类的实现我们只需要继承MethodBeforeAdvice并重写before方法
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
/**
* @author pww
* @date 2021/9/26
* @apiNote
*/
public class MyAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("前置增强");
}
}
后置通知:AfterAdvice
一般不用这个类而是使用下面的AfterReturningAdvice。
后置通知:AfterReturningAdvice //有异常不执行,方法会因异常而结束,无返回值
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
/**
* @author pww
* @date 2021/9/26
* @apiNote
*/
public class MyAfter implements AfterReturningAdvice {
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("后置增强");
}
}
异常通知:ThrowsAdvice
注意这个类中方法需要我们自己选择要实现的方法(也就是自己写不能直接ctrl+O了)
import org.springframework.aop.ThrowsAdvice;
/**
* @author pww
* @date 2021/9/26
* @apiNote
*/
public class MyThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(Exception e) throws Throwable{
System.out.println("出异常了..."+e);
}
}
环绕通知:MethodInterceptor
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* @author pww
* @date 2021/9/26
* @apiNote
*/
public class MyIntercept implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("环绕前");
Object res = methodInvocation.proceed();
System.out.println("环绕后");
return res;
}
}
spring中的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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
">
<!-- 核心业务bean-->
<bean class="com.qf.entity.User" destroy-method="destroy" init-method="init">
<property name="name" value="zs"></property>
</bean>
<bean id="userService" class="com.qf.service.impl.UserServiceImpl"></bean>
<!-- 增强类的bean-->
<bean id="myAdvice" class="com.qf.advice.MyAdvice"></bean>
<bean id="myAfter" class="com.qf.advice.MyAfter"></bean>
<bean id="exception" class="com.qf.advice.MyThrowsAdvice"></bean>
<bean id="myIntercept" class="com.qf.advice.MyIntercept"></bean>
<bean class="com.qf.utils.MyBeanPostProcessor"></bean>
<!-- AOP 配置将增强植入切点-->
<aop:config>
<!-- 设置切点规则
*:代表返回值任意 add:切点方法名 ():无参 (..)任意参数类型或无参-->
<aop:pointcut id="myPoint" expression="execution(* com.qf.service.*..*(..))"/>
<!-- 引入切点和增强-->
<aop:advisor advice-ref="myAdvice" pointcut-ref="myPoint"/>
<aop:advisor advice-ref="myAfter" pointcut-ref="myPoint"/>
<aop:advisor advice-ref="exception" pointcut-ref="myPoint"/>
<aop:advisor advice-ref="myIntercept" pointcut-ref="myPoint"/>
</aop:config>
</beans>