Spring-AOP学习笔记-03通知
Posted Moon&&Dragon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring-AOP学习笔记-03通知相关的知识,希望对你有一定的参考价值。
文章目录
5 通知的类型和使用
5.1 Before
前置通知,该通知是在连接点之前实现的,增强了连接点的前置方法,在前置方法中,我们可以拿到这个连接点,但是不可以对原来连接点方法的执行进行组织。
书写一个切面类,里面书写一个前置方法,在这个方法中我们拿到连接点
public class MyAspect {
// 前置方法
public void before(JoinPoint joinPoint) throws Throwable {
System.out.println("前置方法执行了,准备执行"+joinPoint.getSignature());
}
}
配置配置文件
<?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: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">
<!--需要被代理的类-->
<bean id="Man" class="com.moon.point.Man"/>
<!--切面类-->
<bean id="aspect" class="com.moon.aspect.MyAspect"/>
<!--配置aop-->
<aop:config>
<!--配置aop切点-->
<aop:pointcut id="point" expression="execution(public * com.moon..Man.*(..))"/>
<!--配置切面切入-->
<aop:aspect ref="aspect">
<!--配置前置通知,切面的方法 切点-->
<aop:before method="before" pointcut-ref="point" />
</aop:aspect>
</aop:config>
</beans>
结果:
5.2 After Advice
after后置方法是分为三类,主要是针对方法执行后三种状态,分别可以获得结果,捕获异常,finally执行。
在AfterAdvice中,同样也可以获得连接点JoinPoint
5.2.1 After-finally
我们使用的afterAdvice其实就是After-finally,是放在finally块中,不管方法执行结果是什么,都会执行。
在After-finally中,同样也可以获得连接点JoinPoint
切面:
public class MyAspect {
// 前置方法
public void before(JoinPoint joinPoint) throws Throwable {
System.out.println("前置方法执行了,准备执行"+joinPoint.getSignature());
}
// 后置方法
public void after(JoinPoint joinPoint) throws Throwable {
System.out.println("后置方法执行了,执行完了"+joinPoint.getSignature());
}
}
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: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">
<!--需要被代理的类-->
<bean id="Man" class="com.moon.point.Man"/>
<!--切面类-->
<bean id="aspect" class="com.moon.aspect.MyAspect"/>
<!--配置aop-->
<aop:config>
<!--配置aop切点-->
<aop:pointcut id="point" expression="execution(public * com.moon..Man.*(..))"/>
<!--配置切面切入-->
<aop:aspect ref="aspect">
<!--配置前置通知,切面的方法 切点-->
<aop:before method="before" pointcut-ref="point" />
<!--配置后置通知,切面方法 切点-->
<aop:after method="after" pointcut-ref="point" />
</aop:aspect>
</aop:config>
</beans>
结果:
5.2.2 After-returning
AfterReturning是放在连接点执行后面,可以获得连接点执行完返回的值,同样也可以拿到连接点JoinPoint
这里我们直接拿返回的值,就不拿连接点
切面:
public class MyAspect {
// 前置方法
public void before(JoinPoint joinPoint) throws Throwable {
System.out.println("前置方法执行了,准备执行"+joinPoint.getSignature());
}
// 后置返回方法
public void afterReturning(Object result){
System.out.println("后置返回方法执行");
System.out.println("返回值为:"+result);
}
}
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: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">
<!--需要被代理的类-->
<bean id="Man" class="com.moon.point.Man"/>
<!--切面类-->
<bean id="aspect" class="com.moon.aspect.MyAspect"/>
<!--配置aop-->
<aop:config>
<!--配置aop切点-->
<aop:pointcut id="point" expression="execution(public * com.moon..Man.*(..))"/>
<!--配置切面切入-->
<aop:aspect ref="aspect">
<!--配置前置通知,切面的方法 切点-->
<aop:before method="before" pointcut-ref="point" />
<!--配置后置返回通知,切面方法
切点
返回值接收对象-->
<aop:after-returning method="afterReturning"
pointcut-ref="point"
returning="result"/>
</aop:aspect>
</aop:config>
</beans>
结果:
这里的eat方法没有设置返回值,所以返回值为null
5.2.3 After-throwing
后置异常通知,顾名思义,就是在连接点方法发生异常的时候,才会执行,其实这个通知是放在catch块里面的,用来捕获异常。
注意:
- 异常通知和返回结果通知是互斥的,俩者只有一个会被执行,如果出现异常就拿不到返回值,拿到返回值就说明没有异常。
- 正常的后置通知,是放在finally块中,所以一定会被执行。
切面:
public class MyAspect {
// 前置方法
public void before(JoinPoint joinPoint) throws Throwable {
System.out.println("前置方法执行了,准备执行"+joinPoint.getSignature());
}
// 后置异常方法
public void afterThrowing(Exception e){
System.out.println("后置异常方法执行");
System.out.println("异常信息为:"+e.getMessage());
}
}
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: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">
<!--需要被代理的类-->
<bean id="Man" class="com.moon.point.Man"/>
<!--切面类-->
<bean id="aspect" class="com.moon.aspect.MyAspect"/>
<!--配置aop-->
<aop:config>
<!--配置aop切点-->
<aop:pointcut id="point" expression="execution(public * com.moon..Man.*(..))"/>
<!--配置切面切入-->
<aop:aspect ref="aspect">
<!--配置前置通知,切面的方法 切点-->
<aop:before method="before" pointcut-ref="point" />
<!--配置后置返回通知,切面方法
切点
异常接收对象-->
<aop:after-throwing method="afterThrowing"
pointcut-ref="point"
throwing="e"/>
</aop:aspect>
</aop:config>
</beans>
这里对man类,代理的目标类进行修改,抛一个异常
public class Man implements Person{
@Override
public void eat() {
System.out.println("吃饭");
throw new RuntimeException("它没异常,我制造异常,哎,就是玩");
}
}
结果:
5.3 Around Advice
AroundAdvice,环绕通知,该通知的特点是可以自定义代理,很类似一个代理类,把连接点方法直接给我们,我们可以选择执行或者不执行,默认是不执行的,这里我们拿的连接点就需要是ProceedingJoinPoint,该连接点仅支持环绕通知。
切面:
public class MyAspect {
// 环绕通知方法
public Object around(ProceedingJoinPoint joinPoint)throws Throwable{
try {
System.out.println("前置通知");
// 通过proceed控制目标方法的执行
Object proceed = joinPoint.proceed();
//返回值后置通知
System.out.println("返回值是"+proceed+",返回值后置通知");
return proceed;
} catch (Throwable throwable) {
System.out.println("异常通知:异常信息为:"+throwable.getMessage());
// 为了避免事务失效,所以要将异常跑出去ΩΩ
throw throwable;
} finally {
System.out.println("后置通知");
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: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">
<!--需要被代理的类-->
<bean id="Man" class="com.moon.point.Man"/>
<!--切面类-->
<bean id="aspect" class="com.moon.aspect.MyAspect"/>
<!--配置aop-->
<aop:config>
<!--配置aop切点-->
<aop:pointcut id="point" expression="execution(public * com.moon..Man.*(..))"/>
<!--配置切面切入-->
<aop:aspect ref="aspect">
<!--配置环绕通知-->
<aop:around method="around" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
</beans>
结果:
5.4 执行顺序
以上是关于Spring-AOP学习笔记-03通知的主要内容,如果未能解决你的问题,请参考以下文章