Spring的AOP面向切面 知识点速查

AOP在Spring中原理

通过实现BeanPostProcessor接口的postProcessBeforeInitialization和postProcessAfterInitialization方法,在初始化前后用代理对象加强原来的类

实现方式

  • 预编译:AspectJ
  • 运行期动态代理(JDK动态代理、CGLib动态代理):SpringAOP、JbossAOP

AOP的相关术语

  • jointpoint(连接点):是指那些被拦截到的点。在spring中是指方法,因为spring只支持方法类型的连接点。
  • pointcut(切入点):对哪些joinpoint进行拦截
  • advice(通知/增强):拦截到的jionpoint所做的事情。方法层面的。
    • 前置通知
    • 后置通知
    • 异常通知(抛出异常)
    • 最终通知(无论如何都执行)
    • 环绕通知(方法执行的前后都通知,甚至可以阻止目标方法执行)
  • introduction(引介):特殊的通知,类层面的。
  • target(目标对象):代理的目标对象
  • weaving(织入):把增强应用到目标对象来创建新的代理对象的过程
  • proxy(代理):被AOP织入增强后产生的结果代理类
  • aspect(切面):切入点+通知的结合
    • advisor:一般的切面,advice本身就是一个切面,对目标类所有方法进行拦截
    • PointcutAdvisor:代表具有切点的切面,可以指定拦截目标类哪些方法
    • IntroductionAdvisor:引介切面

底层实现

  • JDK动态代理:对接口做动态代理。代理类继承InvocationHandler接口使用Proxy.newProxyInstance(被代理的接口)
  • CGLIB的动态代理:对实现类做子类增强。使用Enhancer增强

总结

  • spring在运行期间,生成动态代理对象,不需要特殊的编译器
  • spring AOP的底层是通过JDK动态代理或CGLib动态代理技术为目标Bean执行横向织入
    • 若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理
    • 若目标对象没有实现任何接口,spring使用CGLib库生成目标对象的子类
  • 程序中优先对接口创建代理,便于程序解耦维护
  • 标记为final的方法,不能被代理,因为无法进行覆盖
    • JDK动态代理,是针对接口生成子类,接口中方法不能使用final修饰
    • CGLib是针对目标类生产子类,因此类或方法不能使用final
  • spring只支持方法的连接点,不提供属性的连接点

AspectJ用法

通知类型

  • @Before 前置通知
  • @AfterReturning 后置通知
  • @Around 环绕通知
  • @AfterThrowing 异常抛出通知
  • @After 最终final通知

切入点表达式

语法: execution(<访问修饰符>? <返回类型> <方法名>(<参数>) <异常>) 举例:

  • 匹配所有类public方法 execution(public * *(..))
  • 匹配指定包下所有类方法 execution(* top.linxz.dao.(..)) 不包含字包
    • 包含子包execution( top.linxz.dao..(..)) ..表示包、子孙包下所有类
  • 匹配指定类所有方法 execution(* top.linxz.service.UserService.*(..))
  • 匹配实现特定接口所有类方法execution(* top.linxz.dao.GenericDAO+.*(..))
  • 匹配所有save开头的方法 execution(* save*(..))

通知的使用

  • 配置Aspect
@Aspect
public class MyAspectAnno{
    ...
}
  • 前置通知
@Before(value="execution(* top.linxz.java.UserDao(..))")
public void before(JoinPoint joinPoint){
    //joinPoint就是切到的方法
}
  • 后置通知
@AfterReturning(value="execution(* top.linxz.java.UserDao(..))", returning="returning")
public void afterReturing(Object returning){
    //这个returning就是拿到的返回值
}
  • 环绕通知
@Around(value="execution(* top.linxz.java.UserDao(..))", returning="returning")
public Object afterReturing(ProceedingJoinPoint joinPoint){
    System.out.println("环绕前通知")
    Object obj=joinPoint.proceed();//执行目标方法,如果不调用,目标方法就被拦截了。
    System.out.println("环绕后通知")
    return obj;
}
  • 异常通知
@AfterThrowing(value="execution(* top.linxz.java.UserDao(..))",throwing="e")
public void afterThrowing(Throwable e){

}
  • 最终通知,无论如何即使有异常也执行
@After(value="execution(* top.linxz.java.UserDao(..))")
public void afterThrowing(Throwable e){

}
  • @Pointcut为切点命名
    • 切点方法必须为private void 无参数方法,方法名为切点名
    • 当通知多个切点时,可以使用||进行连接

参考

  1. Spring AOP,https://class.imooc.com/course/587
  2. 基于AspectJ的AOP开发,https://class.imooc.com/course/588

原文发布于微信公众号 - 林欣哲(gh_aba6caba3ac7)

原文发表时间:2018-05-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一英里广度一英寸深度的学习

Spring 基础

interface声明接口,接口中的函数不用public/private,但是要匹配参数和异常。

10710
来自专栏JMCui

再学习之Spring(面向切面编程).

一、概念 1、理论     把横切关注点和业务逻辑相分离是面向切面编程所要解决的问题。如果要重用通用功能的话,最常见的面向对象技术是继承(inheritance...

28450
来自专栏李家的小酒馆

AOP的具体实践-简化结果返回的处理

  以前学习Spring的时候着重学习过AOP概念,但是一直也没有用上,唯一碰到过的就是Spring内置的事务管理。现在碰到过一些结果后面的操作适合用到,所以这...

12720
来自专栏C#

C#操作XML的通用方法总结

    在.net的项目开发中,经常会对XML文件进行操作,由于XML文件可以实现跨平台传输,较多的应用在数据传输中,特总结以下几种常用的XML操作方法: ...

37390
来自专栏xingoo, 一个梦想做发明家的程序员

【Spring实战】—— 9 AOP环绕通知

假如有这么一个场景,需要统计某个方法执行的时间,如何做呢?   典型的会想到在方法执行前记录时间,方法执行后再次记录,得出运行的时间。 如果采用Sp...

24250
来自专栏cs

spring aop概念以及jdk的动态代理

AOP(Aspect-Oriented Programming),又称为面向切面编程。作为一种编程思想,AOP是 OOP(Object-Oriented Pro...

10840
来自专栏精讲JAVA

Spring AOP 的实现原理

AOP(Aspect Orient Programming),我们一般称为面向方面(切面)编程,作为面向对象的一种补充,用于处理系统中分布于各个模块的横切关注点...

50270
来自专栏Kiba518

【我们一起写框架】C#的AOP框架

因为,AOP单独设计的框架几乎是无法使用的。普遍的情况是,AOP要是和其他设计模式结合在一起使用。

14230
来自专栏javathings

Spring 中 AOP 的实现

AOP 称为面向切面编程,在程序开发中,AOP 技术可以在不改变原有方法代码的情况下,把逻辑直接插入到方法上。Spring AOP 的大致原理主要依靠的是动态代...

12140
来自专栏青青天空树

spring基础(3:面向切面编程)

  Spring的基础是IOC和AOP,前面两节对IOC和DI做了简单总结,这里再对AOP进行一个学习总结,Spring基础就算有一个初步了解了。

11120

扫码关注云+社区

领取腾讯云代金券