AOP基本知识
AOP (Aspect Oriented Programming) 面向切面编程
-
程序运行期间,将某段代码动态切入到指定方法的指定位置并运行(降低耦合)
JDK自带动态代理
位于反射包下,内有一个Proxy包,包下有一个方法为newProxyInstance,JDK主要是依赖该方法创建动态代理对象并动态切入新的扩展功能,可降低程序的耦合性。
该方法传入三个参数,分别是类加载器,该类所实现的接口(故无接口对象不可使用JDK自带的动态代理,但是Spring的AOP是可以实现无接口动态代理的),还有一个是方法执行器,该执行器帮助目标对象执行目标方法。
方法执行器仍需要传入三个参数,第一个是Object类型的代理对象,用来交由JDK使用,第二个是Method类型的参数,传入需要执行的目标方法,底层由反射机制实现(调用invoke方法执行,这里直接传入对象的类型和参数列表即可),第三个为Object类型的数组,传入执行方法所需要的参数。
如果拿到了代理对象,该代理对象的类型并不是被代理对象的原类型或者父类,而是一个形如$Proxy的类型,该类型与原类型没有任何类型上的关联,但是因为他获取了该被代理对象的同一个接口,通过该接口获取类型一遍执行方法。
Spring动态代理(AOP)
AOP术语
- 横切关注点 –关注于每个方法的同一位置(开始,返回,结束…)
- 通知方法 –在横切关注点调用的方法
- 切面类 –通知方法所属的类
- 连接点 –每个方法的每个位置
- 切入点 –真正需要执行额外代码的位置
- 切入点表达式 –在众多连接点中选出感兴趣的点
步骤
- 导包
- 写配置
- 将目标类和切面类加入到IOC容器中
- 在切面类上加入@Aspect注解
- 告诉Spring切面类里面的每一个方法何时何地运行
- @Before 在执行目标方法之前运行
- 写切入点表达式–value = “execution(方法权限 返回值类型 全类名.指定方法或*(参数类型…))”
- @After 在目标方法结束之后运行
- @AfterReturning 在目标方法正常返回后运行
- @AfterThrowing 在目标方法抛出异常后运行
- @Around 是Spring中最强大的通知
- 环绕通知包含前置通知,返回通知,异常通知,后置通知
- 环绕通知中有一个参数,ProceedingJoinPoint,其含有一个方法–proceed(利用反射调用目标方法运行,等同于method.invoke)
- @Before 在执行目标方法之前运行
- 开启基于注解的AOP模式(配置文件中)–
AOP细节
- AOP底层就是动态代理,容器中保存的不是本类对象,而是本类对象的代理对象,$Proxy,使用本类类型获取对象是不可能获取到的。通过接口类型即可获取到所需对象,因为这是本类对象和代理对象唯一的联系,但一般不把接口类型放入容器中。
- 如果为未实现本类接口的创建代理对象,实现的对象类型就用本类类型获取。(该代理对象通过cglib创建一个内部类,该内部类了该类的所有方法)。
-
- 切入点表示的准确写法
- execution(访问权限 返回值类型 全方法名(参数表))
- 通配符 * :匹配一个或者多个字符 /匹配任意一个参数/匹配一层路径
- .. : 匹配任意多个参数和任意类型参数/匹配任意多层路径
- JoinPoint 封装了当前目标方法的详细信息
- joinPoint.getArgs –获取目标方法运行时使用的参数
- joinPoint.getSignature().getName() –获取到方法签名后再获取想要的值(方法名称)
- 指定参数接收异常和返回值 –returning = “参数名” throwing = “参数名”