Spring中的通知类型
通知类型,是按照在目标方法的前后顺序来决定的,比如在目标方法前或者后面执行,同时还需要在配置文件XML中进行各项通知的配置,通过aop:config 标签实现。
先在配置文件中配置好相应的切入点(pointcut),也就是配置目标方法:
<!--配置代理,通过AOP的配置完成对目标类产生代理-->
<aop:config>
<!--通过表达式配置哪些类的哪些方法需要进行增强-->
<!--也就是配置切入点-->
<!-- * 代表任意返回值-->
<!-- .. 代表任意参数-->
<aop:pointcut id="pointcut1" expression="execution(* SpringAopdemo.ProductDaoImpl.save(..))"/>
<aop:pointcut id="pointcut2" expression="execution(* SpringAopdemo.ProductDaoImpl.del(..))"/>
<aop:pointcut id="pointcut3" expression="execution(* SpringAopdemo.ProductDaoImpl.update(..))"/>
<aop:pointcut id="pointcut4" expression="execution(* SpringAopdemo.ProductDaoImpl.find(..))"/>
</aop:config>
所有的通知都必须配置在 aop:aspect 标签中,处于 aop:config 标签内,用ref = “目标方法类名”的方式,指定目标方法存放的类,使用pointcut-ref 标签用来指定配置好的切入点。
-
前置通知(能够获取切入点(JoinPoint)信息,其实每个通知都能获取切入点信息,如方法名,参数等)(标签:aop:before)
在目标方法之前进行操作,可以用来校验权限操作等
XML前置通知配置:
<!--配置切面-->
<!--配置通知和指定切入点-->
<!--指定切面类,也就是增强方法的类-->
<aop:aspect ref="myAspect">
<!--配置通知(增强方法),和指定的切入点(目标方法,也就是save方法)-->
<!--前置通知 能够获得切入点信息-->
<aop:before method="checkPri" pointcut-ref="pointcut1"></aop:before>
</aop:aspect>
增强方法 checkPri:
// 前置通知,能够获得切入点信息
// 通过JoinPoint类 获得目标方法
public void checkPri(JoinPoint joinPoint){
System.out.println("权限校验========" + joinPoint);
}
- 后置通知(能够获取切入点(JoinPoint)信息和目标方法返回值(Object result),一般可以用来记录操作日志)(标签:after-returning)
XML配置:
<!--后置通知,能够获得切入点信息和目标方法返回值,需要配置 returning 参数名字-->
<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"></aop:after-returning>
需要注意的是,增强方法 writeLog 中定义的返回值参数,需要和 returning 定义的参数名一致。
增强方法 writeLog:
// 后置通知,能够获取切入点信息和返回值
public void writeLog(JoinPoint joinPoint,Object result){
System.out.println("记录日志========" + joinPoint +"===" + result);
}
- 环绕通知(功能最强的一个通知,因为它可以阻止目标方法的运行,因为环绕通知执行在目标方法前后。可以用作运行时间性能监控)(通过ProceedingJoinPoint类的proceed()方法来执行目标方法)(标签:aop:around)
XML配置:
<!--环绕通知-->
<aop:around method="around" pointcut-ref="pointcut3"/>
around 增强方法:
// 环绕通知,
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前通知========");
//通过ProceedingJoinPoint 的 proceed 方法 执行目标方法,如果不执行就可以阻止目标方法执行。
//由于目标方法可能存在返回值,所以需要返回一个object对象
Object object = joinPoint.proceed();
System.out.println("环绕后通知========");
return object;
}
- 异常抛出通知(能够获取到异常信息)(在目标方法有异常抛出的时候,才会执行,可以用于事务管理,当事务中抛出错误,可以执行回滚)(标签:aop:after-throwing)
XML配置:
<!--异常通知,当目标方法抛出异常的时候执行,能够获取到异常信息-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
需要注意的是,afterThrowing 增强方法中传入的参数需要和throwing属性定义的名称 “ex” 一致。
afterThrowing 增强方法
// 异常抛出通知,能获取到异常通知信息
public void afterThrowing(Throwable ex){
//使用getMessage() 方法获取异常信息
System.out.println("抛出异常========" + ex.getMessage());
}
- 最终通知(相当于finally代码块中内容,最后总是会执行,无论有无异常)(标签:aop:after)
XML配置:
<!--最终通知,总是会被执行,无论有无异常-->
<aop:after method="after" pointcut-ref="pointcut4"/>
after 增强方法:
// 最终通知:相当于finally代码块中内容,最后总是会执行
public void after() {
System.out.println("最终通知========");
}
- 引介通知
完整的applicationContext.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:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--Spring的注解开发:组件扫描,扫描需要使用注解的类包(类上注解:可以直接使用属性注入的注解)-->
<!--扫描是为扫描类上的注解-->
<!--<context:component-scan base-package="SpringAopdemo"/>-->
<bean id="ProductDao" class="SpringAopdemo.ProductDaoImpl"/>
<bean id="myAspect" class="SpringAopdemo.MyAspectXML"/>
<!--配置代理,通过AOP的配置完成对目标类产生代理-->
<aop:config>
<!--通过表达式配置哪些类的哪些方法需要进行增强-->
<!--也就是配置切入点-->
<!-- * 代表任意返回值-->
<!-- .. 代表任意参数-->
<aop:pointcut id="pointcut1" expression="execution(* SpringAopdemo.ProductDaoImpl.save(..))"/>
<aop:pointcut id="pointcut2" expression="execution(* SpringAopdemo.ProductDaoImpl.del(..))"/>
<aop:pointcut id="pointcut3" expression="execution(* SpringAopdemo.ProductDaoImpl.update(..))"/>
<aop:pointcut id="pointcut4" expression="execution(* SpringAopdemo.ProductDaoImpl.find(..))"/>
<!--配置切面-->
<!--配置通知和指定切入点-->
<!--指定切面类,也就是增强方法的类-->
<aop:aspect ref="myAspect">
<!--配置通知(增强方法),和指定的切入点(被增强的方法,也就是save方法)-->
<!--前置通知 能够获得切入点信息-->
<aop:before method="checkPri" pointcut-ref="pointcut1"></aop:before>
<!--后置通知,能够获得切入点信息和目标方法返回值,需要配置 returning 参数名字-->
<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"></aop:after-returning>
<!--环绕通知-->
<aop:around method="around" pointcut-ref="pointcut3"/>
<!--异常通知,当目标方法抛出异常的时候执行,能够获取到异常信息-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
<!--最终通知,总是会被执行,无论有无异常-->
<aop:after method="after" pointcut-ref="pointcut4"/>
</aop:aspect>
</aop:config>
</beans>