AOP 原理解析 跳转逻辑 代码演示

AOP 原理解析 跳转逻辑 代码演示

建议大家先看“三、总结”,有一个总体认识比较好

视频总比文章更好理解

一、AOP功能测试

image-20200529222027235

如果都放在了MathCalculator代码里,那就是一种耦合的方式

image-20200529222119307

所以定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里,然后执行

image-20200529223257175

 通知方法:
* 前置通知(@Before):logStart:在目标方法(div)运行之前运行
* 后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
* 返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
* 异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行

先不用环绕通知,尝试前面4个。注意不是Junit的@Before,@After

是org.aspectj.lang.annotation.After;

@Before("top.p3wj.aop.MathCalculator.div")

如果想切MathCalculator的所有方法(且不区分参数,加"…"),即MathCalculator.*(…)

1.1

image-20200529224223102

但是看起来非常繁琐,有公共的切入点,所以可以提取出来。定义一个方法

image-20200529233816416

1.2 加入到容器中

image-20200529225252909

1.3 告诉哪一个类是切面类

image-20200529231426671

1.4 但是最后记住还要开启AspectJ。给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】

image-20200529230229273

1.5 测试一下是否成功

image-20200529234453223

发现并没有输出相应的东西,这是因为这是我们自己new的,只要容器中的组件才可以使用切面的功能

1.5.1 带异常

image-20200529234643728

这下就有了

1.5.2 不带异常

image-20200529234849476

2.1 那么怎么拿到运行时的信息呢?JoinPoint

2.1.1

JoinPoint.getSignature获得方法签名

image-20200529235918427

获得方法名

image-20200529235944269

参数列表

image-20200530000140392

2.1.2

怎么获得返回值呢?returning属性

image-20200530000332367

returning指定谁来封装这个返回值,比如我们用Object result来接受所有的返回值

image-20200601091041227

2.1.3 获得异常,通过throwing

也跟returning一样要指定

image-20200601092640346

不然会报红色,

image-20200601092728808

这个也一样,如果不指定,spring不知道这个exception要干什么

加上后用1/0看一下结果

image-20200601093132330

那么没有这个@AfterThrowing呢?

image-20200601093242622

我们发现是对这个异常没有进行我们的一个处理的,并没有输出那一句话。

2.1.4 JoinPoint位置

image-20200601093603512

我们发现,JoinPotin如果不放在第一个参数,spring是无法解析的

看一下异常:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.context.event.internalEventListenerProcessor': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut 

放在第一位就正常了

image-20200601095034789

image-20200601095227532

二、AOP原理

2.1- @EnableAspectJAutoProxy

AOP就是从@EnableAspectJAutoProxy开始的,加了就有AOP,不加就没有

image-20200601095551805

我们点进去看一下

image-20200601095644226

发现有ImportBeanDefinitionRegistrar,这是之前学的可以给容器bean中自定义注册

image-20200601095738427

英文不好,我就用Translation插件翻译了,大家可以在plugins中搜索安装

可以自定义地来注册,给BeanDefinitionRegistry

我们回到以前看看以前怎么做的,回到MainConfig2

image-20200601103527154

ImportSelector

image-20200601103554549

ImportBeanDefinitionRegistrar

image-20200601103627304

image-20200601103704464

那么AspectJAutoProxyRegistrar注册了什么bean呢?我们打一个断点debug一下
在这里插入图片描述

image-20200601104144543

注册这个组件,如果需要的情况下

image-20200601104347510

调用另一个方法,并传了AnnotationAwareAspectJAutoProxyCreator.class,我们step into进去瞧瞧

image-20200601104610923

3.1 判断是否容器中包含org.springframework.aop.config.internalAutoProxyCreator

3.2 包含则取得这个org.springframework.aop.config.internalAutoProxyCreator

3.3判断这个名字是否等于

image-20200601104811458

对应的他想注册这个

image-20200601104852093

AnnotationAwareAspectJAutoProxyCreator

他这个是判断有了就:

image-20200601105132380

但是我们没有。。。第一次

所以进行了else

image-20200601105150595

3.4

定义一个bean

image-20200601105307014

3.5

image-20200601105350821

然后这个bean的名就叫org.springframework.aop.config.internalAutoProxyCreator

4.1好了,这个beanDefinition就返回了,我们进行下一步

image-20200601105642399

把@EnableAspectJAutoProxy这个注解的信息拿来

4.2 拿来看这个proxyTargetClass,exposeProxy属性是否为true

image-20200601105853715

4.3 这个后来再说

如果为true,就做一些什么操作。

那么,重点就在于他给容器注册了一个AnnotationAwareAspectJAutoProxyCreator,把这个的功能研究出来了,那么AOP功能就出来了。以后也一样的,看见有@EnableXX的注解,就再去看看他给容器注册了什么组件,再去看这些组件的功能是什么

image-20200601110455241

5.那我们就来看一下AnnotationAwareAspectJAutoProxyCreator

5.1 它有很多的继承关系,大家可以放大看一下

AnnotationAwareAspectJAutoProxyCreator

image-20200601110940446

注意XXBeanPostProcessor,bean的后置处理器

BeanFactoryAware,能把工厂传进来的

image-20200601111108286

2.2- AnnotationAwareAspectJAutoProxy

只要分析清楚作为后置处理器和BeanFactory做了哪些工作,整个aop的流畅我们就清楚了

因为是从AbstractAutoProxyCreator开始实现SmartInstantiationAwareBeanPostProcessorBeanFactoryAware接口的

我们点进去看一下

image-20200601112854708

我们发现是它进行setBeanFactory的,我们把断点打在这

image-20200601113005975

只要是postProcessXX乱七八糟的,都是跟后置处理器有关的

image-20200601113426892

我们把所有跟后置处理器有关的逻辑都打上断点

直接返回,或返回空方法的我们就不管了

image-20200601113228756

打上断点:

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException

image-20200601122232476

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
   

image-20200601122324655

注意有的方法名字有点像,

image-20200601122409855

一个是postProcessBeforeInstantiation,一个是postProcessBeforeInitialization

一些不是重写的,自己定义的我们就不打断点了,例如

image-20200601122602218

我们继续上一层:

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值