1.基于xml配置的spring aop
2.基于注解配置的aop
AOP常用的实现方式有两种,一种是采用声明的方式来实现(基于XML),一种是采用注解的方式来实现(基于AspectJ)。
首先复习下AOP中一些比较重要的概念:
Joinpoint(连接点):程序执行时的某个特定的点,在Spring中就是某一个方法的执行 。
Pointcut(切点):说的通俗点,spring中AOP的切点就是指一些方法的集合,而这些方法是需要被增强、被代理的。一般都是按照一定的约定规则来表示的,如正则表达式等。切点是由一类连接点组成。
Advice(通知):还是说的通俗点,就是在指定切点上要干些什么。
Advisor(通知器):其实就是切点和通知的结合 。
一、基于XML配置的Spring AOP
采用声明的方式实现(在XML文件中配置),大致步骤为:配置文件中配置pointcut, 在java中用编写实际的aspect 类, 针对对切入点进行相关的业务处理。
切面类:
package com.spring.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class AopAspect { /** * 前置通知:目标方法调用之前执行的代码 * @param jp */ public void doBefore(JoinPoint jp){ System.out.println("===========执行前置通知============"); } /** * 后置返回通知:目标方法正常结束后执行的代码 * 返回通知是可以访问到目标方法的返回值的 * @param jp * @param result */ public void doAfterReturning(JoinPoint jp,String result){ System.out.println("===========执行后置通知============"); System.out.println("返回值result==================="+result); } /** * 最终通知:目标方法调用之后执行的代码(无论目标方法是否出现异常均执行) * 因为方法可能会出现异常,所以不能返回方法的返回值 * @param jp */ public void doAfter(JoinPoint jp){ System.out.println("===========执行最终通知============"); } /** * * 异常通知:目标方法抛出异常时执行的代码 * 可以访问到异常对象 * @param jp * @param ex */ public void doAfterThrowing(JoinPoint jp,Exception ex){ System.out.println("===========执行异常通知============"); } /** * 环绕通知:目标方法调用前后执行的代码,可以在方法调用前后完成自定义的行为。 * 包围一个连接点(join point)的通知。它会在切入点方法执行前执行同时方法结束也会执行对应的部分。 * 主要是调用proceed()方法来执行切入点方法,来作为环绕通知前后方法的分水岭。 * * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。 * 而且环绕通知必须有返回值,返回值即为目标方法的返回值 * @param pjp * @return * @throws Throwable */ public Object doAround(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("======执行环绕通知开始========="); // 调用方法的参数 Object[] args = pjp.getArgs(); // 调用的方法名 String method = pjp.getSignature().getName(); // 获取目标对象 Object target = pjp.getTarget(); // 执行完方法的返回值 // 调用proceed()方法,就会触发切入点方法执行 Object result=pjp.proceed(); System.out.println("输出,方法名:" + method + ";目标对象:" + target + ";返回值:" + result); System.out.println("======执行环绕通知结束========="); return result; } }
<!-- 声明通知类 --> <bean id="aspectBean" class="com.spring.aop.AopAspect" /> <aop:config> <aop:aspect ref="aspectBean"> <aop:pointcut id="pointcut" expression="execution(* com.spring.service.impl.UserManagerServiceImpl..*(..))"/> <aop:before method="doBefore" pointcut-ref="pointcut"/> <aop:after-returning method="doAfterReturning" pointcut-ref="pointcut" returning="result"/> <aop:after method="doAfter" pointcut-ref="pointcut" /> <aop:around method="doAround" pointcut-ref="pointcut"/> <aop:after-throwing method="doAfterThrowing" pointcut-ref="pointcut" throwing="ex"/> </aop:aspect> </aop:config>
注解:
<!-- 声明spring对@AspectJ的支持 --> <aop:aspectj-autoproxy/>
@Aspect public class AopAspectJ { /** * 必须为final String类型的,注解里要使用的变量只能是静态常量类型的 */ public static final String EDP="execution(* com.spring.service.impl.UserManagerServiceImpl..*(..))"; /** * 切面的前置方法 即方法执行前拦截到的方法 * 在目标方法执行之前的通知 * @param jp */ @Before(EDP) public void doBefore(JoinPoint jp){ System.out.println("=========执行前置通知=========="); } /** * 在方法正常执行通过之后执行的通知叫做返回通知 * 可以返回到方法的返回值 在注解后加入returning * @param jp * @param result */ @AfterReturning(value=EDP,returning="result") public void doAfterReturning(JoinPoint jp,String result){ System.out.println("===========执行后置通知============"); } /** * 最终通知:目标方法调用之后执行的通知(无论目标方法是否出现异常均执行) * @param jp */ @After(value=EDP) public void doAfter(JoinPoint jp){ System.out.println("===========执行最终通知============"); } /** * 环绕通知:目标方法调用前后执行的通知,可以在方法调用前后完成自定义的行为。 * @param pjp * @return * @throws Throwable */ @Around(EDP) public Object doAround(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("======执行环绕通知开始========="); // 调用方法的参数 Object[] args = pjp.getArgs(); // 调用的方法名 String method = pjp.getSignature().getName(); // 获取目标对象 Object target = pjp.getTarget(); // 执行完方法的返回值 // 调用proceed()方法,就会触发切入点方法执行 Object result=pjp.proceed(); System.out.println("输出,方法名:" + method + ";目标对象:" + target + ";返回值:" + result); System.out.println("======执行环绕通知结束========="); return result; } /** * 在目标方法非正常执行完成, 抛出异常的时候会走此方法 * @param jp * @param ex */ @AfterThrowing(value=EDP,throwing="ex") public void doAfterThrowing(JoinPoint jp,Exception ex) { System.out.println("===========执行异常通知============"); } }