spring(二) AOP之AspectJ框架的使用
前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么。而今天要学习spring的第二个重点,AOP。一篇讲解不完,所以这篇文章主要介绍一下什么是AOP,如何去理解AOP。理解完之后,在spring中如何使用AspectJ AOP框架的。看得懂,写的出spring配置的那么就学的差不多了。加油。建议都自己手动实现一遍,这样才能更好的理解。
--WH
一、什么是AOP?
AOP:面向切面编程,采用横向抽取机制,取代了传统的纵向继承
IOC:控制反转
跟IOC一样,我也不知道,这么高大上的名称,被吓坏了,MD,但是通过前面一节的学习,IOC不就是让spring给我们new对象吗,而不需要我们自己创建,
而AOP是一种面向切面的思想,但是我们平常说的spring使用了AOP,实际上说的是spring实现AOP思想的底层原理,而底层原理就是使用动态代理来增强某个方法。所以平常说AOP技术实际上就是指通过动态代理来对方法进行增强。
比如:我们需要对一个已经写好的类中的方法进行增强,在不改动该类方法的代码的情况下,如何做呢?
传统纵向继承
编写一个类,继承该类,重写该类中的这种需要增强的方法,这样确实可以达到我们的目的,但是一旦需要修改的方法所属的类不是一个类,那么就需要在多写很多子类,增加很多方法,编程量就是一个很大的问题,并且后期要修改,工作量也很大。
横向抽取机制,将要增强所用到的代码提取到一个类中,然后对需要增强的方法通过代理类去将其增强即可。
二、动态代理的两个方式
JDK动态代理。接口+实现类
cglib字节码增强。 实现类
为了更好的理解spring的AOP技术,我们应该手动编写以上两种实现动态代理的方法,然后才能体会到spring实现AOP技术所带来的便利。
2.1、JDK动态代理。
要使用JDK动态代理的类,必须要有接口。这是前提条件。
编写UserService接口和UserServiceImpl。
创建代理类的工厂proxyFactory
增强代码的类
测试testApp
测试结果 成功增强了userServiceImpl对象的add方法。如果别的类有需要被增强的方法,那么同样通过创建工厂代理就可以拿到对应的代理对象。然后进行加强
2.2、cglib动态代理。
被代理的对象不需要在实现接口,要求就放松了很多。很多时候都采用cglib来进行动态代理。
需要导入两个jar包
spring已经将cglib和asm整合到了spring-core-3.2.0.jar中,所以我们导入spring的jar包就不需要在重复导这两个包了。
跟JDK动态代理的编写流程是一样的
UserServiceImpl。没有接口了
增强方法的类
创建代理的工厂(和jdk动态代理有区别)
测试
成功增强方法。
注意:CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑,所以 说被代理的类不能有final关键字
三、spring中使用AOP的相关术语
3.1、Target:目标类,需要被增强的类,也就是上面我们写的UserServiceImpl。
3.2、JointPoint:连接点,目标类上需要被增强的方法,(这些方法可以被增强,也可以不增强,也就是说目标类中所有的方法都可以称为是连接点)
3.3、PointCut:切入点,被增强的方法(已经确定这个方法要被增强),切入点就是一个连接点的子集
3.4、Advice:增强/通知,增强的代码,也就是上面将增强的代码凑成的一个类。类中的每个方法都代表一个增强的功能代码,这个类中的方法就被称为通知
3.5、weaving:织入,将切入点和通知结合,从没被增强到已经增强的过程
3.6、Aspect:切面,切入点和通知结合,切入点 和 通知点 多点形成面 特殊情况:一个切入点 和 一个通知
画张图就可以理解了。
3.7、Introduction(引介) 特殊的通知,可以对类增强,添加方法或字段。(知道)
四、spring如何帮我们实现AOP技术(初级版)
spring创建代理工厂bean,属于半自动,思路跟我们用JDK动态代理和cglib动态代理是一样的,只是spring通过ioc帮我们创建这些对象,工厂也是由spring提供。唯一的不同是,我们编写的通知类(之后将其叫成切面类,也就是放增强的代码方法的类) 必须实现MethodInterceptor(注意导包时的问题,这个名称跟cglib中的那个一样,不要导错了)接口,并实现invoke方法,这里就是编写如何增强切入点,好比上面jdk动态代理和cglib代理中的匿名内部类中的方法一样。具体下面讲解。
导入jar包
spring : 4个核心 + 1个依赖
spring aop联盟:
spring aop 实现:
UserServiceImpl
MySpect 切面类,
applicationcontext.xml。
测试
总结:这种方式属性半自动的,需要配置工厂bean,并且目标类的确定太小了,每次只能指定一个目标类,如果我们想对别的类也进行加强,那么就需要在工厂bean中又配置一个目标类,这就体现不出spring的优势了。不推荐使用这种。了解整个发展过程即可
五、spring实现AOP技术(中级 掌握)
全自动过程。直接覆盖很多目标类,不需要在一个个对目标类进行编写通知和工厂了。
其他都一样,配置文件不一样。切入点就不单单是一个目标类了。而是一个范围。
切面类还是跟上面一样
测试: 成功
总结:相比初级的aop实现,好的地方在不用在自己设置工厂bean了,还在直接大范围的指定代理目标类,而不是一个类只能被指定一次。这就是全自动,不用我们配置工厂bean
,spring帮我们都做好了。我们只需要关注切面类,也就是通知和切入点的结合即可。
六、使用AspectJ框架(xml方式)实现aop(高级,推荐)
使用这个的好处在于,我们都不需要在切面类中实现什么通知类型接口了,通知类型接口也在配置文件中编写,而切面类只要关注增强的方法代码即可。
导包:新增两个aspect支持的jar包
aop联盟:com.springsource.org.aopalliance-1.0.0.jar
spring aop支持:spring-aop-3.2.0.RELEASE.jar
aspect 规范:com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring aspect 支持:spring-aspects-3.2.0.RELEASE.jar
AspectJ规定通知类型
6个,知道5个,掌握一个
1.before:前置通知(应用:各种校验)
在方法执行前执行,如果通知抛出异常,阻止方法运行
2.afterReturning:后置通知(应用:常规数据处理)
方法正常返回后执行,如果方法中抛出异常,通知无法执行
必须在方法执行后才执行,所以可以获得方法的返回值。
3.around:环绕通知(应用:十分强大,可以做任何事情) 【掌握】
方法执行前后分别执行,可以阻止方法的执行。要求必须手动的执行目标方法。
4.afterThrowing:抛出异常通知(应用:包装异常信息)
方法抛出异常后执行,如果方法没有抛出异常,无法执行
5.after:最终通知(应用:清理现场)
方法执行完毕后执行,无论方法中是否出现异常
配置文件
通知类型的详解
切面类
测试:
总结:使用AspectJ框架实现AOP,好处很多,关注的点只有切面类(不需要实现通知类型接口),切入点范围,还有通知类型。所以在配置文件中,也只需要配置这三个关键的东西即可,具体看上面的配置文件
七、使用AspectJ框架(注解方式)实现aop(高级,推荐)
使用注解的话,很简单,就是把xml方式用注解给替代,其中也就做6件事
1、将切面类配置给spring,相当于<bean id="" class="切面类全限定类名">
@component
2、将切面类申明为切面
@Aspect
3、将目标类配置给spring
@component 如何不编写名称的话,那么要获取该对象,则使用userServiceImpl进行获取。
4、申明目标类切入点范围
1.方法必须private,没有返回值,没有参数
2.之后使用将其当成方法调用。例如:@After("myPointcut()")
@Pointcut("execution(* com.wuhao.aspectj.annotation.*.*(..))")
5、编写相应的通知
@Before 前置
@AfterReturning 后置,可以获得返回值,必须在注解中确定返回值参数名称。
@AfterThrowing 抛出异常,可以获得具体异常信息,必须在注解确定第二个参数名称
@Around 环绕[]
@After 最终
6:必须在xml中扫描注解和启用aop
7、测试
总结;注解的编写也很简单,要会写注解,首先的知道xml是如何实现的,然后一步步用注解来替代xml的内容即可。并且要知道使用AspectJ框架需要配置哪些内容,就三个点,
xml:
目标类bean
切面类bean
<aop:config>
<aop:aspect ref="myAspectId"> //切面
<aop:pointcut expression="execution(* com.wuhao.aspectj.*.*(..))" id="myPointCutId"/> //切入点范围:<aop:pointcut/>
<aop:around method="myAround" pointcut-ref="myPointCutId"/> //通知类型:<aop:around/>
</aop:config>
八、总结
基本上把spring中使用AOP的技术讲清楚了,可能一开始很不习惯,用多了自然就习惯了,并且建议手写你jdk代理和cglib代理,这样一步步来,就更容易理解在spring中应用AOP的技术的编写代码了。下一篇还会对spring中使用AOP的技术进一步讲解,这一篇相等于写一个aop的helloworld一样。
spring(二) AOP之AspectJ框架的使用的更多相关文章
- spring学习(二) ———— AOP之AspectJ框架的使用
前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...
- Spring的AOP基于AspectJ的注解方式开发2
参考自黑马培训机构 上一篇博客提到了在配置文件中开启aop的注解开发,以及简单使用了@Before,@Aspect 这是为了告诉spring为前置通知和切面类 接下来介绍aop的注解的通知类型,和切入 ...
- Spring的AOP基于AspectJ的注解方式开发1
参考自黑马培训机构 创建项目,引入jar包 编写目标类,切面类并完成配置 package spring.day2_aop2; /* * 编写目标类 */ public class OrderDao { ...
- Spring的AOP基于AspectJ的注解方式开发3
上上偏博客介绍了@Aspect,@Before 上篇博客介绍了spring的AOP开发的注解通知类型:@Before,@AfterThrowing,@After,@AfterReturning,@Ar ...
- spring中AOP的AspectJ的Execution表达式
AspectJ的Execution表达式: 使用springAOP定义pointcut里面的execution表达式: execution()函数是常用的切点函数 "execution(* ...
- 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)
一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...
- Spring aop与AspectJ的区别?
根据我看spring官方文档的理解(不出意外是最正确的答案): ①选择spring的AOP还是AspectJ? spring确实有自己的AOP.功能已经基本够用了,除非你的要在接口上动态代理或者方法拦 ...
- Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)
一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法. ...
- Spring 实践 -AOP
Spring 实践 标签: Java与设计模式 AOP引介 AOP(Aspect Oriented Programing)面向切面编程采用横向抽取机制,以取代传统的纵向继承体系的重复性代码(如性能监控 ...
随机推荐
- mysql 打开sql日志,记录所有sql
我使用的mysql版本为:5.7.11 win7环境 记录下下载地址,省得每次百度搜了:http://dev.mysql.com/downloads/installer/ mysql 默认没有开启sq ...
- python书籍推荐
python书籍推荐列表: 技巧:关于如何在windows平台上行获取目录下的文件名称.(我的python书籍的位置E:\Python\Python_book) D:\>e: E:\>cd ...
- HDU 4256 The Famous Clock
The Famous Clock Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- winsshfs的快速入手
之前在公司使用mac ,并且通过mac下的osfuse和sshfs连接,直接将虚拟机的文件目录同步到了本地,并且可以进行实时操作修改,对于写项目,确实是省了很大一部分上传的精力. 于是在自己的win下 ...
- [Linux] PHP程序员玩转Linux系列-lnmp环境的搭建
1.PHP程序员玩转Linux系列-怎么安装使用CentOS 在平常的工作中,我作为PHP程序员经常要搭建一下环境,这个环境就是Linux系统下安装nginx,php,mysql这三个软件,对软件进行 ...
- Omi教程-生命周期和事件处理
生命周期 名称 含义 时机 constructor 构造函数 new的时候 install 初始化安装,这可以拿到用户传进的data进行处理 实例化 installed 安装完成,HTML已经插入页面 ...
- Codeforces Good Bye 2016 题解
好久没有fst题了...比赛先A了前4题然后发现room里有人已经X完题了没办法只能去打E题,结果差一点点打完...然后C题fst掉了结果就掉rating 了...下面放题解 ### [A. New ...
- Codeforces Round #372 +#373 部分题解
用了两场比赛上Div 1感觉自己好腊鸡的说...以下是这两场比赛的部分题解(不得不说有个黄学长来抱大腿还是非常爽的) Round #372 : Div 2 A:Crazy Computer 题意:给定 ...
- Java显式锁学习总结之二:使用AbstractQueuedSynchronizer构建同步组件
Jdk1.5中包含了并发大神Doug Lea写的并发工具包java.util.concurrent,这个工具包中包含了显示锁和其他的实用同步组件.Doug Lea在构建锁和组件的时候,大多是以队列同步 ...
- rips中如何使用PHP虚拟机自带函数--token_get_all
这两天在看rips源码,发现,它在审计php代码时调用了php虚拟机自带的token_get_all此函数. 这一函数会将php源码按照内置的规则进行归纳,并输出成数组格式. 如: <?php ...