【Spring注解驱动开发】中篇
AOP
面向切面编程
在程序运行过程中将某段代码切入到指定方法/指定位置运行的编程方式
==底层:动态代理==
功能测试
导入aop模块:spring-aspects
定义一个业务逻辑类(MathCalculator),要求在业务逻辑种进行日志打印(方法运行之前、方法运行之后、出现异常……)
定义一个日志切面类(LogAspect),里面的方法需要动态感知 MathCalculator.div 运行到哪里并打印相关信息
通知方法:
- 前置通知( @Before ):LogStart
- 后置通知( @After ):LogEnd
- 返回通知( @AfterReturning ):LogReturn
- 异常通知( @AfterThrowing ):LogException
- 环绕通知( @Around ):动态代理,手动推进目标方法运行( joinPoint.proceed() )
给日志切面类标注通知注解
将 业务逻辑类 和 日志切面类 都加入到容器中
告诉Spring哪个类是切面类:给切面类上加注解
@Aspect
在配置类上加注解:
@EnableAspectJAutoProxy
Spring中很多的
@Enablexxx
直接上代码!
1 | //业务逻辑类 |
1 | //切面类 |
1 | //主配置类 |
AOP原理
==源码分析:看给容器中注册了什么组件、组件如何工作、有什么功能==
@EnalbleAspectJAutoProxy
@Import({AspectJAutoProxyRegistrar.class})
:给容器中导入 AspectJAutoProxyRegistrar利用 AspectJAutoProxyRegistrar 自定义给容器中注册bean
给容器中注册一个名叫 internalAutoProxyCreator ,
类型为 AnnotationAwareAspectJAutoProxyCreator 的组件
接下来我们就详细看一下 AnnotationAwareAspectJAutoProxyCreator 是个什么东西:
先康康继承树:
重点关注 后置处理器 和 自动装配BeanFactory
我们从上往下慢慢看!
1.先从父类 AbstractAutoProxyCreator 开始看!
1
2
3
4
5
6
7
8//实现BeanFactory的方法
public void setBeanFactory(BeanFactory beanFactory)
//有后置处理器相关的方法
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
public boolean postProcessAfterInstantiation(Object bean, String beanName)
public Object postProcessBeforeInitialization(Object bean, String beanName)
public Object postProcessAfterInitialization( Object bean, String beanName)2.再看 AbstractAdvisorAutoProxyCreator !
1
2
3
4
5
6
7
8
9
10
11//重写了setBeanFactory方法
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
if (...) {
...
} else {
//内部调用了initBeanFactory方法
this.initBeanFactory((ConfigurableListableBeanFactory)beanFactory);
}
}3.继续向下看子类 AspectJAwareAdvisorAutoProxyCreator !
1
//emmmmm,方法都跟 后置处理器 或者 自动装配BeanFactory 没啥关系,就不看了
4.最后看 AnnotationAwareAspectJAutoProxyCreator !
1
2
3//又重写了该方法,相当于父类 setBeanFactory() 时还得调它
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory)流程:
1.传入主配置类,创建ioc容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
2.注册配置类,调用
refresh()
,刷新容器(就跟初始化容器一样)3. refresh() 中:
注册 bean 的后置处理器来方便拦截 bean 的创建,进去康康
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// 1.先获取ioc容器中需要创建对象的所有 BeanPostProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 2.给容器中加别的BeanPostProcessor
beanFactory.addBeanPostProcessor
(new PostProcessorRegistrationDelegate.BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 3.优先注册实现了接口 PriorityOrdered 的 BeanPostProcessor
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
pp = (BeanPostProcessor)beanFactory
.getBean(ppName,BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
}
// 4.再注册实现了 Ordered 接口的 BeanPostProcessor
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
// 5.最后注册没实现优先级接口的 BeanPostProcessor
else {
nonOrderedPostProcessorNames.add(ppName);
}
// 6.注册BeanPostProcessor,实际上是创建 BeanPostProcessor 对象,保存在容器中创建 internalAutoProxyCreator 的 BeanPostProcessor
1. 创建 Bean 的实例
populateBean()
:给 bean 的各种属性赋值initializeBean()
:初始化 beaninvokeAwareMethods()
:处理Aware接口的方法回调applyBeanPostProcessorsBeforeInitialization()
:应用后置处理器的beforeInitialization()
invokeInitMethods()
:执行自定义初始化方法applyBeanPostProcessorsAfterInitialization()
:应用后置处理器的afterInitialization()
BeanPostProcessor 创建成功
把 BeanPostProcessor 注册到 BeanFactory中:
beanFactory.addBeanPostProcessor(postProcessor)
4.finishBeanFactoryInitialization(beanFactory):完成 BeanFactory初始化工作
遍历获取容器中所有的 Bean ,依次创建对象
getBean()
—>doGetBean()
—>getSingleton()
创建 bean
先去缓存中康康,如果没有再创建 bean
createBean()
:创建 beanresolveBeforeInstantiation(beanName, mbd)
希望后置处理器在此处能返回一个代理对象,如果能返回代理对象就使用,不能就继续执行下面的操作
doCreateBean(beanName, mbdToUse,args)
:真正去创建一个bean实例