知识储备:详解Spring中AOP原理(基于注解版)2

接着上一篇博客讲,上一篇博客地址:https://blog.csdn.net/qq_36625757/article/details/83652173

8.之前我们说过,测试方法在运行时new了一个AnnotationConfigApplicationContext传入一个配置类,调用了refresh()方法,在refresh()方法中,首先调用registerBeanPostProcessors(beanFactory);创建并初始化后置处理器,也就是1-6步,之后又调用了finishBeanFactoryInitialization(beanFactory);完成BeanFactory的初始化工作,就是来创建剩下的单实例bean,在创建的过程中就会被各个后置处理器拦截掉,下面我们就看看finishBeanFactoryInitialization(beanFactory);

9.进入到finishBeanFactoryInitialization(beanFactory);中,就会看到来到beanFactory.preInstantiateSingletons();创建bean

进入preInstantiateSingletons()方法中,看到在循环所有bean创建对象,通过getBean(beanName);创建。

最后来到doGetBean(name, null, null, false);方法,首先检查单实例的缓存中是否存在当前对象

如果存在就直接返回,否则就通过调用 getSingleton()获得单实例bean,只要创建好的bean就会被缓存起来,保证单实例bean

之后调用createBean(beanName,mbd,args);创建bean

进入到createBean()后就会调用resolveBeforeInstantiation(beanName, mbdToUse);方法,希望后置处理器再此能返回一个代理对象,如果能返回就是使用,否则就调用下面的doCreateBean()创建,对于doCreateBean()方法之前已经详细介绍过了,就是先创建bean实例,然后为bean属性赋值,然后在调用bean的init方法前后调用后置处理器等等操作。

我们来到resolveBeforeInstantiation(beanName, mbdToUse);中看看是如何创建代理对象的

先调用applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);方法,进入其中,看到

先循环所有后置处理器,判断是不是InstantiationAwareBeanPostProcessor类型的后置处理器,如果是就调用他的postProcessBeforeInstantiation(beanClass, beanName);方法,而我们之前已经说过AnnotationAwareAspectJAutoProxyCreator是SmartInstantiationAwareBeanPostProcessor类型的后置处理器,而SmartInstantiationAwareBeanPostProcessor又继承了InstantiationAwareBeanPostProcessor所以AnnotationAwareAspectJAutoProxyCreator也就是InstantiationAwareBeanPostProcessor这种类型的后置处理器,最后就会调用AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation()方法,我们就来看看postProcessBeforeInstantiation()方法都干了写啥?

10.现在我们就关心我们自己创建的LogAspect和MathCal是怎样创建的?我们的MathCal来到org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(Class<?>, String)方法(AnnotationAwareAspectJAutoProxyCreator中没有postProcessBeforeInstantiation()方法的实现,只能调用父类的方法),首先判断是否在advisedBeans中,advisedBeans中保存了所有需要增强的bean。第一次创建是不会包含的,所有if没进去。

 然后就来到第二个判断,首先判断当前bean是否是基础类型即判断是否是实现了Advice,Pointcut,Advisor,AopInfrastructureBean这几个接口,其次还会判断是否是加了@Aspect注解的

最后再通过shouldSkip(beanClass, beanName)判断是否需要跳过

在shouldSkip()中首先获得四个增强器即切面中的四个通知方法,将通知方法包装为InstantiationModelAwarePointcutAdvisor类型的,判断增强器是否是AspectJPointcutAdvisor类型的,而我们的类型不是,机会调用父类的super.shouldSkip(beanClass, beanName);返回false,最后就返回null,来到我们的logConfig配置中

之后又来到org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(Object, String)方法

调用wrapIfNecessary(bean, beanName, cacheKey);进入其中

获得所有候选增强器,然后获得当前bean增强器(通知方法),如何获取呢?

获得增强器后进行排序,最后将增强器封装为Object[]数组

保存当前bean到advisedBeans中表示当前bean已经增强,之后通过createProxy()创建代理对象,进入其中

现获得所有增强器(通知方法),保存到proxyFactory中,通过proxyFactory.getProxy(getProxyClassLoader());获得代理对象

进入其中

spring自动决定使用JDK方式代理还是使用Cglib方式代理

至此就创建出代理对象啦,并返回回去了,以后容器中拿到的就是代理对象了,接下来拿到代理对象,如何调用增强方法,将会在下一篇博客中继续解析。

猜你喜欢

转载自blog.csdn.net/qq_36625757/article/details/83658735