AOP概述
通过AOP提出横切的概念后,在把模块功能正交化的同时,也在此基础上提供一系列横切的灵活实现,比如通过使用Proxy代理对象、拦截器字节码翻译技术等一系列AOP技术,来实现切面应用的各种编织实现和环绕增强。
**面向切面编程(Aspect Oriented Programming,AOP)**其实就是一种关注点分离的技术,为了将业务功能的关注点和通用化功能(日志、缓存、事务等)的关注点分离.
切面(Aspect):指的就是通用功能的代码实现,比如我们上面演示的时间记录切面,日志切面,它们都是普通的Java类:TimeRecordingAspect和LogAspect。
目标对象(Target):要被织入切面的对象,例子中的CtripBookingService,有了AOP,它们可以专注于核心业务逻辑代码了!
切入点(Pointcut):定义通知应该切入到什么地方,Spring支持的切入点就是方法调用,切入点的定义可以使用正则表达式,用以描述什么类型的方法调用。@Pointcut就是用来定义切入点的。
通知(Advice):切面是一个类,而通知就是类里的方法以及这个方法如何织入到目标方法的方式(用@AfterReturning和@Around标注的方法)。我们的例子中只展示了两类通知,根据织入到目标方法方式的不同,一共可以分为5种:
前置通知(Before)
后置通知(AfterReturning)
异常通知(AfterThrowing)
最终通知(After)
环绕通知(Around)
织入(Weaving):AOP实现的过程,即将切面应用到目标对象,从而创建一个新的代理对象的过程,对于Spring来说,就是初始化Context中的对象时,完成织入操作。
通知器(Advisor):通过Advisor把Advice和Pointcut结合起来,这个结合为即开即用地使用AOP基础设施提供了遍历。
代理模式
静态代理模式
在静态代理模式之下,我们显示地创建代理类,代理类持有被代理类的对象,实现与被代理类的相同接口,并且增添相应的业务逻辑,以达到代理的效果。
在静态代理的情况下,每代理一个对象,我们必须在编译时就生成好对应的类,而且需要对接口中所有方法进行代理,会造成不必要的代码冗余,但是这样做的好处就是,代理的调用时直接的方法调用,节省了时间。
动态代理模式
在动态代理的情况下,我们不再为每个类生成一个类来完成代理,而是通过Proxy.newProxyInstance(loader, interfaces, h)来生成代理对象。其三个参数的作用如下表所示:
而InvocationHandler接口中的方法则为public Object invoke(Object proxy, Method method, Object[] args) throws Throwable,其参数作用如下表所示:
在invoker方法中,method就是我们的代理方法,我们可以通过method.invoke(object, args)来直接调用具体对象的方法,由于这个函数的第一个参数是proxy对象,因此我们还需要让handler持有一个真正调用方法的对象,从而能够达到真正的代理效果。
主要是两种,一种是JDK动态代理,一种是Cglib代理。
两者的区别:
1.JDK动态代理只能代理实现了接口的类,动态代理类的字节码在程序运行时由Java反射机制动态生成。
2.Cglib是可以代理没有实现接口的类,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,所以不能对final修饰的类进行代理。底层采用ASM实现。
作者:柠檬乌冬面
链接:https://www.jianshu.com/p/40d0a6ad21d2
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- 代理也是基于类的,静态代理通过编译/手动在编译时写入代理类,以及相应的代理方法,从而完成代理。动态代理在运行时通过指定需要实现的接口,动态拼接生成新的类,并且指定所有方法的回调处理类,从而达到实现一个接口,代理所有方法的效果。
- 动态代理需要通过method进行反射调用。
Spring中的AOP分为两种,一种是由Spring框架实现,基于ProxyFactoryBean的AOP,而另外一种则是基于AspectJ的AOP,我们首先介绍前者,在后续的文章也会介绍后者。
Spring AOP设计
只有当所有的通知执行完毕之后才会调用实际的方法,而之前调用的advice只是为了指定通知的执行顺序,把链中的执行逻辑都罗列清楚,按照具体的方法进行返回操作。
5种消息通知只是spring中原生提供的支持通知,自己在进行实现的时候可以参考实现,但是没有必要非用它本身的模板。
TransactionInterceptor