一、AOP简介
Spring AOP 模块提供了一个符合AOP联盟标准的面相切面编程的实现,它让你可以订阅例如方法拦截器和切点
,从而将逻辑代码分开,简单它们之间的耦合性。AOP可以让一组类共享相同的行为。Spring只支持方法级别的连接点
Spring 提供了4种类型的AOP支持
1、基于代理的Spring AOP
2、纯粹Pojo切面
3、@Aspect驱动的切面
4、注入式的Aspectj的切面
前三种都是Spring Aop实现的变体,Spring Aop构建在动态代理之上,因此Spring Aop局限于方法拦截。
1、Spring Aop 和Aspectj的关系
Aspectj是一套Aop框架,对java语言和语义的扩展。他自己提供了一套关键字,没有安装Aspectj的情况下
无法使用Aspectj。而Spring Aop 依赖的是Spring,仅仅能做到方法级别拦截,所以在Spring使用@Aspectj注解
实现的Aop功能,底层实现还是Spring Aop。Spring缺省使用J2SE动态代理,这样任何接口都可以被代理,也可以使用
CGLIB代理,对于需要代理类不是接口的时候默认使用CGLIB代理。Spring使用了和Aspectj一样的注解,并使用
Aspectj来做切入点解析和匹配,但是Spring Aop运行时仍旧是纯Spring Aop,不依赖Aspectj的编译器或者织入器
2、@EnableAspectJAutoProxy注解使用步骤
1、导入aop模块;Spring AOP:(spring-aspects)
2、定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)
3、定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;
通知方法:
前置通知(@Before):logStart:在目标方法(div)运行之前运行
后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
4、给切面类的目标方法标注何时何地运行(通知注解)
5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中
6、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
7、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】
3、@EnableAspectJAutoProxy注解原理
1、利用@Import向容器中导入AspectJAutoProxyRegistrar组件
AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,通过重新registerBeanDefinitions方法向容器中注册BeanDefinetion
名称internalAutoProxyCreator=AnnotationAwareAspectJAutoProxyCreator
2、AnnotationAwareAspectJAutoProxyCreator
实现了一系列Aware接口,在Bean装载的时候获取BeanFactory,Bean的ClassLoader,实现了Order接口,继承了
PorxyConfig,ProxyConfig中主要封装了代理的通用处理逻辑,比如设置目标类,设置使用cglib还是java proxy等一些基础配置
->AspectJAwareAdvisorAutoProxyCreator
公开了Aspectj的调用上下文,并弄清楚来自同一切面的多个Advisor在Aspectj中的优先级规则。
->AbstractAdvisorAutoProxyCreator
通用自动代理创建器,它基于检查到的每个顾问程序为特定的Bean构建Aop代理。
->AbstractAutoProxyCreator 主要抽象了实现代理的逻辑,就相当于一个代理创建的模版,规定了一些步骤。获取Advisor的
扩展了 ProxyProcessorSupport,实现了SmartInstantiationAwareBeanPostProcessor、BeanFactoryAware 接口
是BeanPostProcessor 实现,该实现使用AOP代理包装每个合格的bean,并在调用bean本身之前委派给指定的拦截器
->implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
关注后置处理器(在bean初始化完成前后做事情)、自动装配BeanFactory
流程:
1)、传入配置类,创建Ioc容器
2)、注册配置类,AnnotationConfigApplicationContext构造方法调用refresh()刷新容器
3)、AbstractApplicationContext 中 registerBeanPostProcessors(beanFactory)注册Bean的后置处理器方便拦截Bean的创建
1)、先获取Ioc容器中已经定义需要创建的所有BeanPostProcessor
2)、给容器增加其他BeanPostProcessor(BeanPostProcessorChecker、ApplicationListenerDetector)
3)、优先注册实现了PriorityOrdered接口的BeanPostProcessor
4)、再给容器中注册实现了Ordered接口的BeanPostProcessor
5)、最后注册没有实现优先级接口的BeanPostProcessor
6)、getBean 过程,时间上就是创建BeanPostProcessor,保存在容器中
1)、创建Bean的实例
2)、populateBean 给Bean的各种属性赋值
3)、initializeBean 初始化Bean
1)、invokeAwareMethods() 处理Aware接口方法回调
2)、applyBeanPostProcessorsBeforeInitialization() 处理后置处理器的postProcessBeforeInitialization方法
3)、invorkInitMethods() 执行自定义的初始化方法
4)、applyBeanPostProcessorsAfterInitialization() 执行后置处理器的postProcessAfterInitialization方法
4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功;--》aspectJAdvisorsBuilder
---上面是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程
4)、finishBeanFactoryInitialization(beanFactory)创建所有剩余的单实例Bean
1)、调用DefaultListableBeanFactroy的preInstantiateSingletons方法,遍历beanDefinitionNames获取beanName
依次调用getBean(beanName) 创建对象 getBean->doGetBean()->getSingleton()->
2)、创建Bean的实例
(AnnotationAwareAspectJAutoProxyCreator在所有bean创建之前会有一个后置处理器,InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation())
1)、AbstractBeanFactory的doGetBean方法真1正实现向Ioc容器获取Bean的功能,也是触发依赖注入功能的地方。正实现向Ioc容器获取Bean的功能,也是触发依赖注入功能的地方。
先从getSingleton先后三级缓存中取是否有被创建过的单例Bean,已创建直接使用,否则再创建,放入缓存
2)、doGetBean,创建单例这里使用了一个匿名内部类调用createBean(),再调用DefaultSingletonBeanRegistry的getSingleton方法,创建Bean实例对象,并且注册给所依赖的对象