从一个示例开始,先自定义一个类:java
package top.callback.demo.bean;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.ApplicationContext;
public class User {
private BeanFactory beanFactory;
private ObjectFactory<ApplicationContext> objectFactory;
// getter & setter
}
复制代码
配置文件:spring
<bean id="user" class="top.callback.demo.bean.User" autowire="byType" />
复制代码
测试程序:markdown
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/application-context.xml");
User user = beanFactory.getBean(User.class);
BeanFactory innerBeanFactory = user.getBeanFactory();
ObjectFactory<ApplicationContext> applicationContext = user.getObjectFactory().getObject();
System.out.println(beanFactory == innerBeanFactory); // false
System.out.println(beanFactory == applicationContext); // true
}
复制代码
为何 beanFactory
不等于 innerBeanFactory
,而等于 applicationContext
?app
按理说,User 对象是从 beanFactory 获取的,那么 user#beanFactory
和 beanFactory 应该是一个东西,但实际上倒是爹生了娃,但亲子鉴定说娃不是亲生的。这时候就要从 ClassPathXmlApplicationContext 入手,去看看他的继承关系是什么样的。框架
若是图片看不清楚,能够自行在 IDEA 里面借助 Diagrms 功能进行查看。从图中能够看到,ClassPathXmlApplicationContext 一路火花带闪电的层层继承,最终成为了 BeanFactory 接口的一个间接实现。因此代码里可使用多态将 ClassPathXmlApplicationContext 的实例赋值给 BeanFactory。ide
在继承链中有一个抽象类 AbstractApplicationContext,其中重载了多个 getBean()
方法用于获取容器内的 Bean。而这些方法无一例外的都调用了 getBeanFactory()
来先获取一个 BeanFactory 实例,进而调用 BeanFactory 的 getBean()
方法实际执行 Bean 获取。测试
意外的是,这个类里的 getBeanFactory()
方法是个抽象方法。查看其返回值 ConfigurableListableBeanFactory 接口的实现,发现不管哪一个实现都是返回自身的 beanFactory
字段,而这个字段的类型都是 DefaultListableBeanFactory。this
同时,在 AbstractApplicationContext 的 prepareBeanFactory()
中也明确指定了要使用的 BeanFactory 实现是经过 getBeanFactory()
方法返回的 DefaultListableBeanFactory。spa
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); // AbstractApplicationContext 663行
复制代码
回到最初的示例,配置文件里指定了以 byType
类型注入的形式进行注入,那么根据上述分析,user#beanFactory
注入的就必定是 DefaultListableBeanFactory。而经过配置文件建立的是 ClassPathXmlApplicationContext 的实例,这两个对象天然就不相等了。代理
至于示例中的 beanFactory
等于 applicationContext
,这是由于在这个示例程序运行过程当中,只有一个 ClassPathXmlApplicationContext 是 ApplicationContext 接口的实现,因此按类型注入下二者其实就是同一个对象。
结合上面的继承关系图能够看出,ClassPathXmlApplicationContext 其实是 BeanFactory 接口的一个最终实现。在其继承链上,BeanFactory 被从 ApplicationContext 接口开始的多个类进行了功能丰富,而且对 BeanFactory 的基础功能进行了代理。官方文档这么描述 BeanFactory 和 ApplicationContext 的关系:
In short, the
BeanFactory
provides the configuration framework and basic functionality, and theApplicationContext
adds more enterprise-specific functionality. TheApplicationContext
is a complete superset of theBeanFactory
and is used exclusively in this chapter in descriptions of Spring’s IoC container.
ApplicationContext 是 BeanFactory 的超集,BeanFactory 仅提供基础功能和配置,ApplicationContext 在其上面增长了更多企业性功能。能够简单的理解为,BeanFactory 是给 Spring 框架自身用的,而 ApplicationContext 是给 Spring 框架的使用者用的。