00:00
好,那我们已经把这个切面,然后还有咱们的一个,呃,这个目标类,然后已经交给了咱们的IOC容器来管理,然后同时呢,咱们也已经通过这个it aspect注解,将咱们当前的组件呢,标识为了一个切面。好,然后下面大家注意啊,我们下面就可以来开启咱们基于注解的AOP的功能了。在这咱们需要来设置一个标签啊,什么标签大家看好,我们需要用到一个命名空间,叫做a op啊,然后咱们所使用的标签叫做aspect j auto proy,大家注意是这个标签啊。好,里面咱们不需要去设置其他属性,然后咱们直接把它设置为单标签就行,那这个标签的作用是用来干嘛的?大家注意啊,是开启基于注解的AOP功能,也就是说我们现在要想来实现这个基于注解的AOP啊,那我们的这个标签大家必须要设置,否则实现不了啊。
01:00
好,那我们现在咱们的这个呃功能咱们已经开启过了,对吧?咱们在这再来写上注意事项,然后在这咱们还需要干什么,在spring然后的配置文件中,然后来设置什么标签叫做a op of aspect的G杠,Auto pro,对吧?然后来开启基于注解的AOP行。然后下面呢,我们是不是就可以来实现功能了,这是咱们的切面,那切面里面写的是什么?大家想一下,切面中咱们来写的是不是抽取横切关注点,把咱们的横切关注点封装为一个方法,然后这个方法呢,就是一个通知对不对?所以说我们在这咱们就可以来写个方法了,然后比如说word的,然后这个方法名咱们叫啥呢?那咱们的通知刚才咱们看了应该有几种啊,一共是五种通知。分别是前置通知、返回通知、异常通知、后置通知,还有环绕通知。好,然后咱们的每一种通知呀,然后它都对应了我们连接点的不同位置,连接点是什么,连接点是我们抽取横切关注点的地方,其实就是咱们的目标对象中的这个方法。
02:12
然后呢,我们现在咱们通过这个代理模式,动态代理咱们能操作的这个目标对象方法执行的过程中啊,然后咱们能操作的位置一共有几个,是不是应该就四个呀。方法执行之前,方法执行之后,然后有异常时,还有final中对不对,咱们说过最后这个环绕通知呢,然后它相当于咱们上面的这四种通知,那下面呢,咱们就来做一个例子,比如说我们拿着前置通知来做一下例子啊。好,比如说我们在在这创建一个前置通知的方法,叫b for before。Advice,然后method,那是不是说你现在你把方法名设置为前置通知的方法,那它就是前置通知,大家说是不是不是啊,我们在这,咱们要想来设置一个前置通知,我们是必须要在这加上一个相对应的注解的。
03:04
什么注解就叫做a before注解?能看懂吧,这个注解就是将咱们当前的方法来标识为前置通知的方法啊。好,那咱们的前置通知里面咱们写什么呢?那前置通知是在什么时候执行的?大家还记得不是在我们当前目标对象方法执行之前来执行,那我们在这个位置,因为它叫local aspect的,那所以咱们在目标对象方法执行之前,咱们是不是要来记录这个方法名,还有参数,但是现在咱们还做不到,咱们一会儿呢在讲如何获取连接点的信息,然后我们现在咱们就先随便说出一句话叫做logo aspect的逗号,然后再来设置,再来显示一个叫前置通知就可以啊。好,但是我们现在咱们用了这个注解之后,大家会发现他报错了,为什么报错呢?大家想想咱们说的这个a op中,我们都要做什么,我们要做的事情就是抽横切关注点封装到切面中,然后封装为一个通知方法。
04:08
然后再把咱们的通知方法通过切入点表达式作用到连接点上,这就是咱们a op中要做的事情,对吧。好,然后呢,我们现在呢,咱们的这个通知咱们已经把它给配置好了,但是我们最终是不是还有一件事情没做,就是要把咱们的通知作用到连接点上,通过谁切入点表达式,所以说为什么它会报错,那是因为咱们这里面呢,有一个属性叫什么属性,你看咱们鼠标放上去有提示,它说value missing对吧,然后啊,这个啊,Saw,然后required什么意思,Required是必须的意思,那说明我们当前咱们的Y流属性是必须要来设置的,对吧。好,那value属性来设置的是谁,就是我们当前咱们的一个切入点表达式,这个大家注意。好,那我们在这咱们就把切入点表达式给设置一下呗,怎么写看好了啊,里面会有需要写一个单词,叫execution,这是固定写法。
05:06
然后我们下面咱们是不是还需要来把咱们的切入,通过切入点表达式来定位到咱们的连接点。那什么是连接点呢?大家想想,那不就是我们抽取横切关注点的地方吗?那换句话来说,就是我们的通知要作用到的目标对象中的某一个方法。所以说咱们的这个表达式呀。我们就需要通过这个表达式来定位到咱们目标对象中的某一个方法上,那怎么来写,大家注意写的非常的,这个怎么说呢,精确,我们从咱们的这个反访问修饰符,到返回值,到咱们的包名,到类名,到方法名,到咱们的参数的类型,我们都是需要把它设置出来的。好,大家注意,那在这大家看好了啊,怎么写啊,首先比如说我们现在要把前置通知作用于我们的目标对象的ADD方法上。那这个时候呢,我们就需要把咱们当前的切入点表达式,然后通过切入点表达式给定位到这儿,那怎么写,首先大家看你看它的返回值,方方法的访问修饰不是public。
06:11
方法的这个返回值呢是int,那所以我们就可以这样去写,帕布返回值为int。那咱们在这能直接写方法名吗?你直接在这写个ADD,大家说那叫ad的方法多了,那你到底是要把哪要作用于咱们的哪一个目标对象中的这个addd方法呢?所以说我们现在你的方法从哪来,从类而来,你的类在哪,在包下面,所以说我们现在就需要把这个方法所在的方法所在的类,以及类所在的包都需要把它给设置出来啊好,所以说是com.a的硅谷,然后点spring.aop.aation。然后再点calculator I'PL然后再点什么方法A方法这个大家能看懂吧。
07:00
好,而且还没设置完,因为我们的A地方啊,它是有参数的,里面有两个参数是都是int类型。咱们在这不需要来设置参数名,因为因为大家想一下你的方法存在重载,那重载它跟参数名没关系,它就跟咱们的参数类型顺序个数有关系,对不对,所以说咱们在这只需要设置个int,再设置个int就完事了。这个大家看好了啊好,那我们现在咱们就已经设置好了。在这的这个标记就是咱们的前置通知的标记,大家会发现这个圆圈里面写个M是方法的意思,然后呢,在我们当前这个方法的上面加了一个半圆,它指的就是在我们目标方法执行之前来执行,能听懂吧,哎,是这样的啊好,那我们现在咱们这个东西就写完了呀,然后大家注意,那我们在这儿可以给大家写个笔记,就是说在切面中,切面中,然后咱们需要干什么啊,需要通过指定的注解,然后将咱们的方法,然后标识为通知方法。
08:09
OK吧,比如说咱们的第一个叫做A比赋,这个东西大家注意是干什么的,是用来标识前置通知的注解,叫做前置通知的注解。那前置通知在什么时候执行,刚才是不是说过了,在目标,在目标对象方法执行之前,然后来执行,哎,这个大家注意啊,行,那下面呢,咱们就测试一下呗,怎么测试,咱们在这来创建一个测试类,然后呢,com.at硅谷点spring,然后点test,然后咱们就叫做a up test。OK,好,然后下面咱们在这来创建一个方法啊,比如说这个方法咱们是通过注解来实现的,那咱们就叫做A,就叫做这个呃,叫做test AOP,然后by all。
09:06
TOK啊行,那大家说我们下面咱们要干啥?首先我们第一步是不是要来获取IOC容器,对不对,因为我们的这个A,咱们也是在IOC的基础上来实现的嘛,对不对,你看咱们的calculator I PL logo aspect的不都是IOC容器中的一个组件嘛,是不是啊,所以说先获取IOC容器。克拉斯帕斯,OK。行,然后把我们当前咱们的配置文件的这个名字呀,然后给他拿过来,然后下面的呢,我们再通过IOC容器来获取咱们当前的这个病。那大家说我们要来获取什么类型的病呀?我们要来获取的是我们的这个目标类类型的这个B吗。那我们获取的到底应该是什么呢?大家想一下,因为我们的a op它的底层用的是代理模式,所以说我们现在咱们应该是来获取的是一个代理对象,对吧?因为代理模式里面就告诉我们,只要咱们为目标对象创建了代理对象之后,我们每一次对目标对象的访问都是通过咱们的代理对象间接来访问的,对不对?所以说我们现在咱们应该来获取的是目标对象啊,在获取的是代理对象啊,那如果你要获取一个这个目标对象的话,你能获取到吗?或者说咱们获取到之后有什么效果呢?大家来看。
10:31
好,咱们在这get b,我来获取,谁叫做calculator I pl.class你看咱们获取的直接就是我们当前的一个目标对象,对不对?目标类的对象,那我们在这直接来执行它的ad方法,一逗号1OK,下面大家看好,我们在这来一个执行。啊,大家看一下,你看他直接报错。这个大家能看懂吗?你看它直接报错,报的错是什么叫no such being DeFinition exception,这个错就非常的神奇,但是其实我们想想,我们也是能够理解的。
11:10
首先他说我们calculator IL类型的这个并没有找到,它不可用,对吧,然后但是我们在咱们的这一个calculator PL上,我们加的有注解,而且我们扫描的时候,咱们有没有扫描到我们当前的这一个类,那绝对是扫描到的。但是我们从IOC容器中能够获取到它吗?获取不到,那大家说这不就跟我们之前所说的代理模式是一个意思吗?咱们只要为目标对象来创建了代理对象,我们每一次来访问他,我们都是要通过谁呀代理对象间接来访问的,你能只现在咱们还能直接通过目标对象来访问吗?那你要还通过目标对象来访问他,那你创建的代理对象有什么用呢?对不对,所以说你看在我们的IOC容器中,它就表现的更明确一些。
12:00
当我们使用了A之后,然后我们现在咱们在IOC容器里面,你压根连你的目标对象你都获取不到。这个大家能看懂吧,好,所以说我们现在我们只能通过谁来访问目标对象中的方法,只能通过代理对象来访问,但是那咱们还是那句话,我也不知道那代理对象的代理类他叫什么,那我怎么来获取他的类,获取他的对象呢?虽然说我们不知道他叫什么,但是我们知道它跟咱们的目标对象来实现的是相同的接口啊。大家想想是不是,你想想我们之前咱们的动态代理,咱们是怎么做的,咱们说了我不知道它叫什么,但是我可以通过向上转型来创建这个接口的对象。对吧,所以说我们在这咱们也是咱们说过通过IOC来获取某个bin的时候,我们不需要通过一个具体的类型来获取你用它所实现的什么,你用它所实现的这个所继承的负类,或说或者说是它所实现的接口是不是都能够获取到,对不对?好,所以说大家看啊,然后在这咱们直接一个ioc.get b里面写谁咱们不知道它的类型,但是我知道它实现的接口一定是calculator,所以说在这点class获得一个calculator对象,然后再来调用其中的ad方法有团老师,那我们现在,那我通过这个类型来获取,那咱们的IOC容器中万一有多个类型匹配的B呢?
13:28
对不对,那我们现在能想到的类型匹配的B是不是一个代理对象,一个是咱们的目标对象,而我们刚才来获得咱们的目标对象的时候,你能获取到吗?大家看一下能获取到吗?获取不到,所以说你在这儿能够获取的一定是一个目标对象,一定是咱们的代理对象,能听懂吧?好,下边我们在这咱们再来一个执行,大家来看,好,这个时候大家看一下,你看这不就有效果了吗?咱们的目标类里面你有没有写什么logo aspect的前置通知没有。
14:01
能看懂吧,但是我们现在咱们在调用这个方法的时候,在这咱们的前置通知是不是被输出了,那这说明啥?说明我们当前咱们的切面有作用了,我们切面中的通知确实是通过我们当前的切入点表达式作用到了我们当前的连接点,没有任何问题啊好,这个大家注意好,然后我们在这咱们这个通过我们的注解,然后我们创建一个方法来封装咱们的横切关注点,然后咱们需要通过一个注解将它标识为通知方法。然后我们需要把我们当前的通知通过咱们的切入点表达式来作用于我们的连接点,好,咱们的a op就完成了。还有最重要的一点就是我们在获取的时候,我们刚才看到的效果是什么?你无法通过IOC容器来获取我们的目标对象,我们只能来获从IOC容器中来获取咱们的代理对象。能听懂吧,好,这个大家要注意啊好。
我来说两句