两个类都实现了同一个接口,但是其中一个类对接口的实现是通过调用另一个类的接口实现来实现的,这就是静态代理模式(也可以说是装饰器模式,这俩区别不大)
这个例子中就是AbstractBeanFactory和AnnotationConfigApplicationContext都实现了BeanFactory,但是AnnotationConfigApplicationContext对BeanFactory的getBean方法是通过调用AbstractBeanFactory对BeanFactory的getBean方法的实现来实现的。
所以说Context和Factory的关系是:Context静态代理了Factory(或者说Context是Factory装饰器),Context持有Factory。
我们都知道Spring的所有对象都是通过getBean获取的。我们接触最多的可能是拿到一个IOC容器(AnnotationConfigApplicationContext context),然后通过context.getBean(XXX.class);
去获取一个bean。当你想看这个方法是怎么实现的时候,你会发现有一堆getBean方法,不知道哪一个才是我们想要看的。
聪明的你可能会想:既然不知道是具体是哪个getBean在真正的去干活去创建对象,那么只要在抽象的接口上打上一个断点,IDEA自然就会帮你找到具体的实现类了。
于是右键点击容器类,选择show Diagram,IDEA就生成了AnnotationConfigApplicationContext的类图
只看接口,我们大概可以知道,所谓的容器,实际上就是有加载资源的能力(ResourceLoader),并且有创建Bean的能力(BeanFactory)。望文生义,大概可以知道容器(AnnotationConfigApplicationContext)的getBean方法应该来源于BeanFactory
找到这个类然后一看:
还真是,虽然还是有很多getBean,但是最多我把这五个getBean都打上断点,肯定能断到我们想要的方法的。打下断点,debug运行:
这里也有好几个getBean方法,官方也在这里醒目的写到“Implementation of BeanFactory interface”。所以这几个方法就是Context实际调用的方法了。
但是这里有一个问题:这些实现方法所在的类(AbstractBeanFactory)并不在我们刚刚看到的容器(AnnotationConfigApplicationContext)的继承树里面。也就是说getBean的具体实现并不在容器进行实现。
看AbstractBeanFactory的继承树发现他也是继承了BeanFactory了
这就有点让人疑惑了,难不成有两个Bean工厂?如果有两个Bean工厂的话为什么在Context打的断点会断到另一个BeanFactory那里呢?怎么想都不可能,所以肯定只有一个真正干活的Bean工厂。而AbstractBeanFactory不出现在AnnotationConfigApplicationContext的继承树里唯一可能的原因就是:AnnotationConfigApplicationContext持有了AbstractBeanFactory(或者他的子类),然后AnnotationConfigApplicationContext被调用getBean的时候实际调用的是AbstractBeanFactory的实现。
把类图的属性打开,可以看到,Context里面确实持有了BeanFactory(也持有了resourceLoader,所以说Context只是组合了这俩东西)。
再点进源码看,发现确实是调用的Factory的getBean
如果你学过设计模式的话可能就会感到有些熟悉:两个类都实现了同一个接口,但是其中一个类对接口的实现是通过调用另一个类的接口实现来实现的,这不就是静态代理模式吗(可以说是装饰器模式,这俩区别不大)
这个例子中就是AbstractBeanFactory和AnnotationConfigApplicationContext都实现了BeanFactory,但是AnnotationConfigApplicationContext对BeanFactory的getBean方法是通过调用AbstractBeanFactory对BeanFactory的getBean方法的实现来实现的。
所以说Context和Factory的关系是:Context静态代理了Factory(或者说Context是Factory装饰器),Context持有Factory。