简介
本文介绍Spring里的BeanFactory。包括:BeanFactory 和 FactoryBean的区别,ApplicationContext的委托逻辑。
BeanFactory 和 FactoryBean
项 | BeanFactory | FactoryBean |
工厂 | 负责生产和管理bean的一个通用工厂。 基于工厂模式实现。 | 也是一个工厂,但只创建一种对象。 |
作用 | 实例化、定位、配置对象及建立其依赖。 IOC容器的核心接口。 | 可以创建复杂的bean。 是一个接口。 Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。 |
实现 | DefaultListableBeanFactory、ApplicationContext、XmlBeanFactory等。 比如:XmlBeanFactory解析XML生成bean,处理对象间的依赖关系。 |
类的关系
在Spring–Bean的创建过程/获取流程 – 自学精灵里可以发现,这几个BeanFactory比较重要:AbstractApplicationContext、DefaultListableBeanFactory、AbstractBeanFactory。那来看一下详细的类关系:
放眼望去,一脸懵逼。那介绍下这些类的作用:
- BeanDefinitionRegistry: Spring 配置文件中每一个节点元素在 Spring 容器里都通过一个 BeanDefinition 对象表示,它描述了 Bean 的配置信息。而 BeanDefinitionRegistry 接口提供了向容器手工注册 BeanDefinition 对象的方法。
- BeanFactory 接口位于类结构树的顶端 ,它最主要的方法就是 getBean(String beanName),该方法从容器中返回特定名称的 Bean,BeanFactory 的功能通过其他的接口得到不断扩展:
- ListableBeanFactory:该接口定义了访问容器中 Bean 基本信息的若干方法,如查看Bean 的个数、获取某一类型 Bean 的配置名、查看容器中是否包括某一 Bean 等方法;
- HierarchicalBeanFactory:父子级联 IOC 容器的接口。
- 子容器可通过接口方法访问父容器; 通过 HierarchicalBeanFactory 接口, Spring 的 IoC 容器可以建立父子层级关联的容器体系,子容器可以访问父容器中的 Bean,但父容器不能访问子容器的 Bean。
- Spring 使用父子容器实现了很多功能,比如在 Spring MVC 中,展现层 Bean 位于一个子容器中,而业务层和持久层的 Bean 位于父容器中。这样,展现层 Bean 就可引用业务层和持久层的 Bean,而业务层和持久层的 Bean 则看不到展现层的 Bean。
- ConfigurableBeanFactory:是一个重要的接口,增强了 IoC 容器的可定制性,它定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法;
- AutowireCapableBeanFactory:定义了将容器中的 Bean 按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法;
- SingletonBeanRegistry:定义了允许在运行期间向容器注册单例 Bean 的方法;
- DefaultSingletonBeanRegistry:有缓存单例对象和单例工厂的属性(map),缓存已经注册的单例的属性(set);有注册单例bean的方法
- 属性
- singletonObjects:这个map缓存了单例对象,bean的名字为key,bean对象为value
- singletonFactories:这个map缓存了单例工厂,bean的名字为key,工厂对象为value
- registeredSingletons:这个set缓存了已经注册的单例。
- 方法
- registerSingleton(String beanName, Object singletonObject):会将单例对象放到singleFactories、registeredSingletons
- 属性
ApplicationContext的委托
AbstractApplicationContext的委托逻辑
AbstractApplicationContext部分源码
public Object getBean(String name) throws BeansException { this.assertBeanFactoryActive(); return this.getBeanFactory().getBean(name); } public <T> T getBean(String name, Class<T> requiredType) throws BeansException { this.assertBeanFactoryActive(); return this.getBeanFactory().getBean(name, requiredType); } public Object getBean(String name, Object... args) throws BeansException { this.assertBeanFactoryActive(); return this.getBeanFactory().getBean(name, args); } public <T> T getBean(Class<T> requiredType) throws BeansException { this.assertBeanFactoryActive(); return this.getBeanFactory().getBean(requiredType); }
可以看到,对BeanFactory的实现都是委托给了getBeanFactory这个方法返回的实例,接口是组合,实现也是组合,这种清晰的设计是学习典范。
getBeanFactory:它是AbstractApplicationContext自己定义的抽象方法,实现类为AbstractRefreshableApplicationContext.class,
public final ConfigurableListableBeanFactory getBeanFactory() { synchronized(this.beanFactoryMonitor) { if (this.beanFactory == null) { throw new IllegalStateException("BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext"); } else { return this.beanFactory; } } }
实现很简单,它返回了它的成员:beanFactory。Spring容器初始化的时候调用refreshBeanFactory方法,该成员变量在refreshBeanFactory方法中实例化。所以容器初始化之后,AbstractApplicationContext就具备了bean管理配置的能力。
看了上述委托的方式,猜测ApplicationContext继承的Message接口也是这么操作的?
查看代码:
public String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) { return this.getMessageSource().getMessage(code, args, defaultMessage, locale); } public String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException { return this.getMessageSource().getMessage(code, args, locale); } public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException { return this.getMessageSource().getMessage(resolvable, locale); }
如上所示,果然如此,Message相关的接口实现,都是getMessageSource()方法返回的实例在承担,getMessageSource()方法返回的是成员变量messageSource,该成员变量也是在Spring容器初始化的时候,调用initMessageSource方法生成的。
请先
!