事实上上一篇文章价值非常小,也有反复造轮子的嫌疑,网上AOP的实例非常多,不胜枚举,事实上我要说的并非这个,我想要说的就是上一节中spring的配置文件:

我们这边并没实用到我们上几节分析的哪几个AOP的主要实现类:ProxyFactoryBean.java , ProxyFactory.java ,AspectJProxyFactory.java ,在我们这个配置文件里,根本没有显示的去配置这些类,那么spring究竟是怎么做到的呢?

大家能够这么想。spring究竟是怎么去杀害目标对象的呢?真正的凶手究竟是谁呢(ProxyFactoryBean?ProxyFactory?AspectJProxyFactory)?在什么时候杀害的呢(Spring IoC容器初始化的哪个阶段做代理的呢?)

事实上。这边有好几个问题

① spring容器里面究竟有几个实例

(事实上这个非常好解决,我们仅仅须要打开refresh方法,看下beanfactory中的beandefinitionMap中有多少个对象就能够知道了)

②spring究竟什么时候偷梁换柱的呢,也就是说,我们的目标对象究竟在spring容器初始化阶段的哪个阶段被换成了代理呢?

关于这个问题,我认为我们应该自己给出答案,还记得我们在分析Spring IoC 源代码的时候,我们说想改动一个bean 大体上仅仅有2个阶段,或者说3个小段

首先是在运行beanfactoryPostProcessor的阶段。我们曾经讲过这个阶段是改动beandefinition。改动了beandefinition就会直接改动了这个bean的生成,所以这个阶段非常有可能是做代理的地方。可是细致一分析,应该也不是,假设在这个阶段代理了,那么假设我们被代理的目标对象实现了其它接口呢,比如InitializingBean,或者定义了init-method这些方法呢,是不是得不到运行呢?所以应该不是

然后第二个最大的疑点就是beanPostProcessor阶段。这个接口又分成了2个阶段,大家应该还记得这个接口的核心接口:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" align="bottom" height="489" width="850">

事实上这2个方法都能够直接暂时改动bean,但最最有可能的就是postProcessAfterInitialization这个接口了。由于我们曾经分析过postProcessAfterInitialization这种方法是在bean初始化过程中最后一个运行的。也就是说,假设在这个阶段,Spring偷偷地替换了bean,对于我们来说是透明的。全然没有感觉,由于bean的一些实例化操作都所有做完了

好了。分析到如今。事实上我就想说我们如今要做的事情就是我们看下IoC 的refresh方法,主要看看一下几点,就知道基于IoC配置的AOP的原理了

①看下beanDefinition

②看下BeanFactoryPostProcessor这个处理

③看下BeanPostProcessor的注冊

④看下我们目标对象在postProcessAfterInitialization这个阶段发生了什么?

⑤看下我们advisor是怎么生成的,代理怎么做的

好了。我们先看第一点:

首先BeanFactory中BeanDefinitionMap的对象是9个,除了我们明面上定义的2个,还有7个我们不知道的bean也生成了(关于这7个是怎么生成的。这边就不细讲了,主要是依据Spring的xml文件的命名空间去做转换然后当做普通的bean处理的),这边最值得怀疑的就是上图中红色标中的前2个(尼玛。看名字就知道了)

我们接着看第二点:

当我们debug已经过了BeanFactoryPostProcessor的运行过后,我们看下beandefinitionMap:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" align="bottom">

看样子并没有进行改动。说明凶手并非BeanFactoryPostProcessor

好了,我们接着看第四点(第三点最后看)。我们将断点打到AbstractAutowireCapableBeanFactory.java的1518行(spring.3.2.5)

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" align="bottom" height="31" width="850">

进入具体方法:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" align="bottom" height="246" width="850">

好了,我们来看下我们目标对象的遗照吧。等下即将被凶手残忍的杀害

到这边为止bean中的对象还是我们的bussinessServiceImpl

接下来凶杀即将開始,当我们运行到一个名字叫org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator$BeanFactoryAdvisorRetrievalHelperAdapter的时候,我们进入一下postProcessAfterInitialization这种方法:AbstractAutoProxyCreator.java的postProcessAfterInitialization方法

进入wrapIfNecessary中

好了,我们再看下究竟用什么刀杀的,进入createProxy方法:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" align="bottom" height="529" width="850">

原来这把刀就是ProxyFactory,哈哈~最终找出原因了

如今我们已经知道凶手是谁。在什么地方杀害的目标对象,那么还剩下最后一个问题,凶手是怎么潜入被害者的房间呢?

我们还是回到我们刚刚没说的第三点:我们看看BeanPostProcessor的注冊,回到refresh方法中的registerBeanPostProcessors方法

看到没有,凶手就是在这个时候潜入房间的,等到下文spring在实例化目标对象的时候,一杀即中

到眼下为止。我们已经基本上知道了凶杀的基本流程,可是细节我们还没有分析。比方说advisor怎么生成的。凶手怎么知道在黑夜中就是要杀bussinessService呢?这些还请大家略微看下就能够了~

今天就到这边了,各位柯南大神,end~

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" align="middle">

最新文章

  1. js的动态加载、缓存、更新以及复用(三)
  2. Twisted安装
  3. 转:strcmp函数实现及分析
  4. Js/Ajax中发送HttpPost请求调用WebService
  5. 如何提高多线程程序的cpu利用率
  6. .net 测试工具类
  7. bzoj 2716 天使玩偶(CDQ分治,BIT)
  8. foreach遍历原理(一)
  9. java反射 实例
  10. sqlserver05 字符串拆分
  11. 代码审查 (Google牛人谈Code Review)
  12. 新浪微博iOS SDK UIImage+WBSDKResize.o
  13. hdu1512 Monkey King
  14. 再起航,我的学习笔记之JavaScript设计模式26(解释器模式)
  15. Python实战之字符串的详细简单练习
  16. 代码之间-论文修改助手v1.0版本发布
  17. Ubuntu18.04更新源
  18. 尚硅谷springboot学习11-占位符
  19. iOS sqlite C语言操作
  20. 3.circle (圆)

热门文章

  1. android基本控件学习-----ImageView
  2. class.getDeclaredFields()与class.getFields()
  3. sublime text3 无法安装插件
  4. 慎用lodash的cloneDeep函数
  5. 源码分析——迁移学习Inception V3网络重训练实现图片分类
  6. Java面试中的多线程问题
  7. 打包python脚本为exe
  8. pt-query-digest 实践(转)
  9. redis参数配置
  10. dubbo zookeeper案例