Spring之AOP
AOP,也叫面向切面编程,也就是一种在系统运行时动态添加代码的方式。
说通俗点,就是规定某些方法在执行前需要做些什么,执行完了之后做些什么。
先介绍几个概念
Joinpoint 连接点 类里面可以被增强的方法就是连接点 eg:想修改某个方法的功能,那么该方法就是连接点
Pointcut 切入点 对Joinpoint进行拦截的定义就是切入点 eg:拦截所有的Insert方法,这个就是切入点
Advice 通知 拦截到Joinpoint之后要做的事情就是通知
Aspect 切面 Pointcut 和 Advice 的结合
Target 目标对象 要增强的类就是目标对象
然后介绍几个注解
@Aspect 表明这是一个切面类
@Pointcut 定义切入点
eg: @Pointcut("excution(* org.sang.aop.service.*.*(..))")
第一个*表示方法返回任意值
第二个*表示service包下的任意类
第三个*表示类中的任意方法
括号中的..表示方法参数任意
@Before 前置通知
该方法在目标方法执行之前执行,通过JoinPoint 参数可以取到目标方法的方法名、修饰符等信息
@After 后置通知
@AfterReturning 返回通知
在该方法中可以获取目标方法的返回值
其中 returning 参数是指返回值的变量名,对应方法的参数
在方法参数中如果result定义为Object 类型,表示目标方法的返回值可以是任意类型
@AfterThrowing 异常通知
@Around 环绕通知
功能最强大的通知,可以实现前置通知、后置通知、异常通知以及返回通知的功能
下面看一个具体的例子:
@Component @Aspect public class UserAspect { @Pointcut("execution(* com.example.yang.service.UserService.*(..))") public void pc() { } @Before(value="pc()") public void before(JoinPoint jp) { String name = jp.getSignature().getName(); System.out.println(name + "方法开始执行!"); } @After(value="pc()") public void after(JoinPoint jp) { String name = jp.getSignature().getName(); System.out.println(name+ "方法执行结束!"); } @AfterReturning(value="pc()", returning="result") public void afterReturning(JoinPoint jp, Object result) { String name = jp.getSignature().getName(); System.out.println(name+"方法的返回值是:"+result); } @AfterThrowing(value="pc()", throwing="e") public void afterThrowing(JoinPoint jp, Exception e) { String name = jp.getSignature().getName(); System.out.println(name + "抛出异常了,异常信息是:"+e.getMessage()); } @Around("pc()") public Object around(ProceedingJoinPoint pjp) { String name = pjp.getSignature().getName(); System.out.println(name+"方法开始执行"); try { Object result = pjp.proceed(); System.out.println(name+"方法的返回值为:"+result); return result; } catch (Throwable e) { System.out.println(name+"方法出现异常"); return null; }finally { System.out.println(name+"方法执行结束"); } } }
使用起来还是挺简单的,就提一下@Around的注意点:
你原本的方法是什么返回值,那么这个around函数的返回值就是什么,
pjp.proceed()虽然会使目标方法继续执行,但是目标方法返回的内容会变成由around方法返回
比如:你的目标方法执行两个操作,一个是输出一句话,一个是return一个字符串
在around方法中虽然执行了pjp.proceed(),只会输出那句话,但是return null