前情回顾:
上文我们一路分析了从容器创建开始直到我们的 AOP 注解导入的核心组件 AnnotationAwareAspectJAutoProxyCreator 执行 postProcessBeforeInstantiation()方法的整个过程
分析得到: 在所有 bean 创建之前, 都会调用 resolveBeforeInstantiation 方法来试图返回一个代理对象
本篇预告
下图可以看到 resolveBeforeInstantiation 方法包含了
- applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
- applyBeanPostProcessorsAfterInitialization(bean, beanName);
两个方法
在本篇我们将完整走完 resolveBeforeInstantiation 全过程, 并一直到返回代理对象为止
调试的起点
开始调试, 还是一路跳到下一断点, 直到 AbstractAutoProxyCreator.postProcessBeforeInstantiation()(从 resolveBeforeInstantiation 方法进入到这里的过程上一篇已经分析了)
可以看到当前的 bean 为 org.springframework.context.event.internalEventListenerProcessor, 和我们要测试的 AOP 无关.
因为当前方法打上了断点, 所以我们调到下一个断点直到来到 class aop.MathCalculator
- @Override
- public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
- Object cacheKey = getCacheKey(beanClass, beanName);
- if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
- if (this.advisedBeans.containsKey(cacheKey)) {
- return null;
- }
- if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
- this.advisedBeans.put(cacheKey, Boolean.FALSE);
- return null;
- }
- }
- // Create proxy here if we have a custom TargetSource.
- // Suppresses unnecessary default instantiation of the target bean:
- // The TargetSource will handle target instances in a custom fashion.
- if (beanName != null) {
- TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
- if (targetSource != null) {
- this.targetSourcedBeans.add(beanName);
- Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
- Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
- this.proxyTypes.put(cacheKey, proxy.getClass());
- return proxy;
- }
- }
- return null;
- }
- postProcessBeforeInstantiation
从上往下一步步 step voer, 下面是对应行的讲解
3, 获取 bean 在容器中的缓存
5, 判断目标源 Bean 中是否存在有当前 bean 的缓存信息.
(可以在 21 行看到添加目标源 bean 的操作, 在 23 行就创建了代理对象. 所以这步也是相当于判断当前 bean 是否已经创建过代理对象.)
因为是第一次执行 MathCalculator 这个 bean, 这里我们是进入判断的
接下来 this.advisedBeans.containsKey(cacheKey) 判断 advisedBeans 中是否有缓存(这里我们将 advisedBeans 称为增强器)
我们这里判断是不满足的, 接着往下走.
9, 进行 isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName) 判断
下面分别进入第九行的两个方法进行查看.
一, isInfrastructureClass(beanClass) 是否是基础类型
进入后我们会发现有如下两个方法
super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass)
先进入父类的 isInfrastructureClass 方法, 经过一系列判断, 最后返回 false, 表明当前 bean 不是基础类型.
接着来到 isAspect(beanClass) , 通过类上是否有 @Aspect 注解来判断这个类是否是切面(这里 MathCalculator 显然不是一个切面)
返回出来可以看到 isInfrastructureClass(beanClass) 的判断为 false
二, shouldSkip 判断是否要跳过
在方法中遍历所有的增强器, 红框中表面获取的增强器便是日志方法.
并判断增强器是否是 AspectJPointcutAdvisor 类型, 我们这里判断不满足
末尾来到父类的 shouldSkip 方法, 进入可以看到直接返回了 false
最终我们来到外层的判断, 可以看到返回了 false
退出 applyBeanPostProcessorsBeforeInstantiation 方法
接着来到下面这块代码, 看注释表明如果存在自定义目标 Source, 我们将在此创建代理对象
step voer, 在 259 行判断 targetSource 为 null, 所以这里是没有自定义目标 Source 的
我们一直往下走, 走完 applyBeanPostProcessorsBeforeInstantiation 方法, 直到回到 resolveBeforeInstantiation 方法, 返回的 bean 为 null
所以接下来也不会进入 applyBeanPostProcessorsAfterInitialization 方法
到此为止, 我们的 resolveBeforeInstantiation 方法执行完了, 从以上可以得知, 方法没有给我们返回代理对象
如下图所示, 我们将接着执行 createBean 流程, 接下来将调用 doCreateBean
postProcessAfterInitialization 方法探究
我们执行 doCreateBean 方法, 来到了配置类的 bean 方法
接着跳到下一个断点直到 postProcessAfterInitialization 方法, 下面的方法栈我们是熟悉的
从 finishBeanFactoryInitialization 一路到 initializeBean
不过我们现在进入的是 postProcessAfterInitialization
从下图的 initializeBean 方法的流程也可以看明白
前面执行完了 applyBeanPostProcessorsBeforeInitialization 和 invokeInitMethods 两个方法
下面进入 postProcessAfterInitialization 方法:
如果先前的代理参考中不存在当前 bean 对象, 就调用 wrapIfNecessary(bean, beanName, cacheKey) 并返回其结果
进入 wrapIfNecessary(进行包装如果需要的话):
- /**
- * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
- * @param bean the raw bean instance
- * @param beanName the name of the bean
- * @param cacheKey the cache key for metadata access
- * @return a proxy wrapping the bean, or the raw bean instance as-is
- */
- protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
- if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
- return bean;
- }
- if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
- return bean;
- }
- if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
- this.advisedBeans.put(cacheKey, Boolean.FALSE);
- return bean;
- }
- // Create proxy if we have advice.
- Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
- if (specificInterceptors != DO_NOT_PROXY) {
- this.advisedBeans.put(cacheKey, Boolean.TRUE);
- Object proxy = createProxy(
- bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
- this.proxyTypes.put(cacheKey, proxy.getClass());
- return proxy;
- }
- this.advisedBeans.put(cacheKey, Boolean.FALSE);
- return bean;
- }
- wrapIfNecessary
9~18 行: 还是先进行判断, 是否是基础类型等, 在这里我们判断都不是
21: 拿到增强器放入 Object[] specificInterceptors 中
24~25: 传入拿到的增强器等信息, 创建代理对象
下面我们着重来看 getAdvicesAndAdvisorsForBean 拿增强器的过程:
一进来先调用 findEligibleAdvisors, 找到合格的增强器(日志方法)
进入 findEligibleAdvisors, 方法先调用 findCandidateAdvisors, 获取所有候选增强器
然后又调用 findAdvisoersThatCanApply 从候选增强器中选出可以用于当前 bean 的
接着判断选出的增强器队列不为空, 就给其排序, 最后返回选出的增强器队列
findCandidateAdvisors 我们就不说了
重点看看 findAdvisoersThatCanApply
如下图, 可以发现它是利用 AopUtils, 也就是 AOP 工具类进行筛选
进入工具类方法, 看到方法又进行了一层判断, 将最终符合条件的增强器 (日志方法) 放入选择队列中
获取完后我们一路返回, 又回到了 findEligibleAdvisors
如下图可以看到, 最终排序完后将返回有五个增强器的增强器队列
创建代理对象
最终我们获取到了需要的增强器 (日志方法) 放入一个叫特殊拦截器的数组(这里暂且称为拦截器数组)
判断不为空后, 将当前 bean 的缓存放入 adviseBeans 中
接着调用 createProxy 来创建代理对象
- /**
- * Create an AOP proxy for the given bean.
- * @param beanClass the class of the bean
- * @param beanName the name of the bean
- * @param specificInterceptors the set of interceptors that is
- * specific to this bean (may be empty, but not null)
- * @param targetSource the TargetSource for the proxy,
- * already pre-configured to access the bean
- * @return the AOP proxy for the bean
- * @see #buildAdvisors
- */
- protected Object createProxy(
- Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
- if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
- AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
- }
- ProxyFactory proxyFactory = new ProxyFactory();
- proxyFactory.copyFrom(this);
- if (!proxyFactory.isProxyTargetClass()) {
- if (shouldProxyTargetClass(beanClass, beanName)) {
- proxyFactory.setProxyTargetClass(true);
- }
- else {
- evaluateProxyInterfaces(beanClass, proxyFactory);
- }
- }
- Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
- proxyFactory.addAdvisors(advisors);
- proxyFactory.setTargetSource(targetSource);
- customizeProxyFactory(proxyFactory);
- proxyFactory.setFrozen(this.freezeProxy);
- if (advisorsPreFiltered()) {
- proxyFactory.setPreFiltered(true);
- }
- return proxyFactory.getProxy(getProxyClassLoader());
- }
- createProxy
从上往下看
19 行创建代理对象对象工厂 proxyFactory ,31~34 在代理对象工厂中加入增强器, 目标 Source 等属性
41 行调用 proxyFactory.getProxy(getProxyClassLoader()) 获取当前 bean 的代理对象
先创建 Aop 代理对象
可以看到结果一系列调用后来到下图, 有 3 种动态代理对象可能返回, 我们这里返回的是 Cglib 动态代理对象
一步步将代理对象返回, 执行完当前 bean 的 applyBeanPostProcessorsAfterInitialization 方法, 返回其代理对象
可以得知: 返回的代理对象将代替 bean 对象存入容器中
到此为止, 我们的代理对象创建步骤就完成了.
总结:
initializeBean 方法在初始化 bean 时, 将通过 applyBeanPostProcessorsAfterInitialization 创建并返回目标 bean 的代理对象, 并存入容器中.
目前为止的过程, 都是在初始化 bean 前完成的
下面两张图中的代码流程是关键
initializeBean 流程:
refresh 流程(AOP 中我们需要了解的):
- postProcessBeanFactory(beanFactory);
- invokeBeanFactoryPostProcessors(beanFactory);
- finishBeanFactoryInitialization(beanFactory);
refresh 完整流程参考如下:
- @Override
- public void refresh() throws BeansException, IllegalStateException {
- synchronized (this.startupShutdownMonitor) {
- // Prepare this context for refreshing.
- prepareRefresh();
- // Tell the subclass to refresh the internal bean factory.
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
- // Prepare the bean factory for use in this context.
- prepareBeanFactory(beanFactory);
- try {
- // Allows post-processing of the bean factory in context subclasses.
- postProcessBeanFactory(beanFactory);
- // Invoke factory processors registered as beans in the context.
- invokeBeanFactoryPostProcessors(beanFactory);
- // Register bean processors that intercept bean creation.
- registerBeanPostProcessors(beanFactory);
- // Initialize message source for this context.
- initMessageSource();
- // Initialize event multicaster for this context.
- initApplicationEventMulticaster();
- // Initialize other special beans in specific context subclasses.
- onRefresh();
- // Check for listener beans and register them.
- registerListeners();
- // Instantiate all remaining (non-lazy-init) singletons.
- finishBeanFactoryInitialization(beanFactory);
- // Last step: publish corresponding event.
- finishRefresh();
- }
- catch (BeansException ex) {
- if (logger.isWarnEnabled()) {
- logger.warn("Exception encountered during context initialization -" +
- "cancelling refresh attempt:" + ex);
- }
- // Destroy already created singletons to avoid dangling resources.
- destroyBeans();
- // Reset 'active' flag.
- cancelRefresh(ex);
- // Propagate exception to caller.
- throw ex;
- }
- finally {
- // Reset common introspection caches in Spring's core, since we
- // might not ever need metadata for singleton beans anymore...
- resetCommonCaches();
- }
- }
- }
- refresh
在下一篇中, 也是本系列的最后一篇, 我们将探究增强器 (日志方法) 是如何通过代理对象, 在代理对象方法执行的时候发挥作用的.
来源: https://www.cnblogs.com/Unicron/p/12433523.html