回顾:
spring框架-认识spring框架(一)
spring框架-认识IOC(二)
目录
AOP综述
AOP是什么
AOP有什么用
AOP怎么用
AOP优点
探索AOP
AOP原理
AOP的动态代理:
JDK代理和CGLib代理我们该用哪个
AOP术语
连接点(JointPoint)
切入点(PointCut)
增强/通知(Advice)
前置通知(MethodBeforeAdvice )
后置通知 (AfterReturningAdvice )
环绕通知(MethodInterceptor)
异常通知(ThrowsAdvice)
引介通知(IntroductionInterceptor)
切面(Aspect)
织入(weaving)
目标对象(target)
顾问(Advisor)
Spring对AOP的支持
知识点
切面类型主要分成了三种
使用引介/引入功能实现为Bean引入新方法
总结
AOP综述
AOP是什么
Aspect-oriented programming 面向切面(方面)编程
AOP有什么用
可以把业务逻辑和系统级的服务进行隔离
系统级的服务像系统的日志,事务,权限验证等
AOP怎么用
动态代理
AOP优点
1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦
2、低侵入式设计,代码的污染极低
3、利用它很容易实现如权限拦截,运行期监控和系统日志等功能
探索AOP
如果没有接触过AOP(面向切面编程)的,可能一时间没办法理解,因为之前都是用JAVA的面向对象编程(OOP),没关系,一步步跟我来学习AOP。
当然如果您是技术大牛,既然您抽出时间查看了虚竹的文章,欢迎纠正文章中的不足和缺陷
我们先来看下来这段《精通Spring4.x 企业应用开发实战》提供的代码片段图上的业务代码被事务管理代码和性能监控代码所包围,而且学过JAVA的都知道,出现重复代码了。出现重复代码那就需要重构代码,代码的重构步骤一般有这两种:
1、抽成方法
2、抽成类
抽取成类的方式我们称之为:纵向抽取
通过继承的方式实现纵向抽取
但是,虚竹发现这种抽取方式在图上的业务中不适用了,因为事务管理代码和性能监控代码是跟对应的业务代码是有逻辑关系的
AOP原理
AOP的底层原理就是动态代理(如果没听过代理模式,可以看看这位大神写的博客给女朋友讲解什么是代理模式)
来源《Spring 实战 (第4版)》一句话:
Spring AOP构建在动态代理基础之上,因此,Spring对AOP的支持局限于方法拦截。
AOP的动态代理:
jdk动态代理
cglib动态代理
Spring在选择用JDK动态代理还是CGLiB动态代理的依据:
(1)当Bean实现接口时,Spring就会用JDK的动态代理
(2)当Bean没有实现接口时,Spring使用CGlib是实现
(3)可以强制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)
JDK代理和CGLib代理我们该用哪个
在《精通Spring4.x 企业应用开发实战》给出了建议:
如果是单例的我们最好使用CGLib代理,如果是多例的我们最好使用JDK代理
原因:
JDK在创建代理对象时的性能要高于CGLib代理,而生成代理对象的运行性能却比CGLib的低。
如果是单例的代理,推荐使用CGLib
现在大家知道什么是AOP了吧:把非业务重复代码横向抽取出来,通过动态代理织入目标业务对象函数中,实现跟之前一样的代码
AOP术语
aop术语不好理解,《精通Spring4.x 企业应用开发实战》书上有提到这些术语,我尽量解释下这些术语
连接点(JointPoint)
一个类中的所有方法都可以被称为连接点
切入点(PointCut)
上面也说了,每个方法都可以称之为连接点,我们具体定位到某一个方法就成为切点。
用注解来说明,被@Log定义的方法就是切入点增强/通知(Advice)
表示添加到切点的一段逻辑代码,并定位连接点的方位信息。
前置通知(MethodBeforeAdvice )
前置通知是在目标方法执行前执行
后置通知 (AfterReturningAdvice )
后置通知是在目标方法执行后才执行 ,可以得到目标方法返回的值 ,但不能改变返回值
环绕通知(MethodInterceptor)
环绕通知有在目标方法执行前的代码,也有在目标方法执行后的代码,可以得到目标方法的值,可以改变这个返回值!
扩展知识点:
spring中的拦截器分两种:
1、HandlerInterceptor
2、MethodInterceptor
HandlerInterceptor是springMVC项目中的拦截器,它拦截的目标是请求的地址,比MethodInterceptor先执行
MethodInterceptor是AOP项目中的拦截器,它拦截的目标是方法,即使不是controller中的方法。
异常通知(ThrowsAdvice)
最适合的场景就是事务管理
引介通知(IntroductionInterceptor)
引介通知比较特殊,上面的四种通知都是在目标方法上织入通知,引介通知是在目标类添加新方法或属性
简单来说就定义了是干什么的,具体是在哪干
Spring AOP提供了5种Advice类型给我们:前置通知、后置通知、返回通知、异常通知、环绕通知给我们使用!
切面(Aspect)
切面由切入点和增强/通知组成
交叉在各个业务逻辑中的系统服务,类似于安全验证,事务处理,日志记录都可以理解为切面
织入(weaving)
就是将切面代码插入到目标对象某个方法的过程,相当于我们在jdk动态代理里面的 invocationHandler接口方法的内容
用注解解释:就是在目标对象某个方法上,打上切面注解
目标对象(target)
切入点和连接点所属的类
顾问(Advisor)
就是通知的一个封装和延伸,可以将通知以更为复杂的方式织入到某些方法中,是将通知包装为更复杂切面的装配器。
Spring对AOP的支持
Spring提供了3种类型的AOP支持:
基于代理的经典SpringAOP
需要实现接口,手动创建代理
纯POJO切面
使用XML配置,aop命名空间
@AspectJ注解驱动的切面
使用注解的方式,这是最简洁和最方便的!
知识点
切面类型主要分成了三种
一般切面
切点切面
引介/引入切面
一般切面,切点切面,引介/引入切面说明:
引介/引入切面有两个实现类:
DefaultIntroductionAdvisor:常用的实现类
DeclareParentsAdvisor:用于实现AspectJ语言的DeclareParent注解表示的引介/引入切面
实际上,我们使用AOP往往是Spring内部使用BeanPostProcessor帮我们创建代理。
这些代理的创建器可以分成三类:
基于Bean配置名规则的自动代理创建器:BeanNameAutoProxyCreator
基于Advisor匹配机制的自动代理创建器:它会对容器所有的Advisor进行扫描,实现类为DefaultAdvisorAutoProxyCreator
基于Bean中的AspectJ注解标签的自动代理创建器:AnnotationAwareAspectJAutoProxyCreator
对应的类继承图:
使用引介/引入功能实现为Bean引入新方法
其实前置通知,后置通知,还是环绕通知,这些都很好理解。整个文章就引介/引入切面比较有趣,我们来实现试试吧
有个服务员的接口:
public class TestAop { @Test public void testAop(){ ApplicationContext ac = new ClassPathXmlApplicationContext("dispatcher-servlet.xml","applicationContext-datasource.xml","applicationContext.xml"); Waiter waiter = ac.getBean("Waiter",Waiter.class); // 调用服务员原有的方法 waiter.greetTo("虚竹"); waiter.serveTo("虚竹"); // 通过引介/引入切面已经将waiter服务员实现了Seller接口,所以可以强制转换 Seller seller = (Seller) waiter; seller.sell("东西", "虚竹"); } }
总结
AOP的底层实现是动态代理,动态代理包含JDK动态代理和CGLib代理。当Bean实现接口时,Spring就会用JDK的动态代理;当Bean没有实现接口时,Spring使用CGlib是实现;可以强制使用CGlib。
如果是单实例,推荐使用CGLib代理,如果是多例的我们最好使用JDK代理。因为CGLib代理对象运行速度要比JDK的代理对象要快
AOP的层面是方法级别的,只能对方法进入拦截
无论是XML方式还是注解方式,原理都一样,我们用注解AOP就够了,简单好用
引介/引入切面是比较有趣的,具体实现上面举例说明了,它可以达到用某个接口的方法,又不入侵代码,低耦合的效果。具体妙处还待开发,后面有发现再补充说明
脑图链接:https://www.processon.com/view/link/5c51671be4b048f108e2aa0f
查看链接可以看到更多信息,脑图的备注没办法导成图片