Spring源码解析 - BeanFactory

时间:2022-11-13 10:10:31

BeanFactory是Spring实现依赖注入的核心接口.提供应用的统一配置注册功能,实现业务开发解偶.使用getBean可以代替单例,原型设计模式.

顶重要的BeanFactory里注释写得太好了.所以咱们先翻译下注释,后面再详细分析.

重点直接看红色标注吧.

The root interface for accessing a Spring bean container.
This is the basic client view of a bean container;
further interfaces such as {@link ListableBeanFactory} and
{@link org.springframework.beans.factory.config.ConfigurableBeanFactory}
are available for specific purposes.

访问一个Spring bean容器的根接口。这是一个bean容器的基本客户端视图;  进一步的接口,如{@link ListableBeanFactory}和  {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}  可用于特殊目的。

This interface is implemented by objects that hold a number of bean definitions,
each uniquely identified by a String name. Depending on the bean definition,
the factory will return either an independent instance of a contained object
(the Prototype design pattern), or a single shared instance (a superior
alternative to the Singleton design pattern, in which the instance is a
singleton in the scope of the factory). Which type of instance will be returned
depends on the bean factory configuration: the API is the same. Since Spring
2.0, further scopes are available depending on the concrete application
context (e.g. "request" and "session" scopes in a web environment).

此接口由持有一些bean定义的对象来实现,每个bean由String字符串唯一标识。根据bean定义,  工厂将返回一个独立对象实例(原型设计模式),或者一个单个共享实例(Singleton设计模式的优雅代替实现,其中该实例是一个factory范围内的单例)。实例的哪种类型将被返回依赖于bean工厂配置:即使API是一样的。从Spring2.0开始,作用域扩展到根据具体的应用上下文,如web环境的request,session。

The point of this approach is that the BeanFactory is a central registry
of application components, and centralizes configuration of application
components (no more do individual objects need to read properties files,
for example). See chapters 4 and 11 of "Expert One-on-One J2EE Design and
Development" for a discussion of the benefits of this approach.

这种方案的关键是,BeanFactory的是应用程序组件注册的中心,同时集中应用程序组件的配置(程序模块不再需要读取诸如properties的配置文件)。这种设计的更多好处讨论详见的<J2EE设计开发编程指南>第4和第11章.

强烈推荐看这本书,就是国内不好买了.

Note that it is generally better to rely on Dependency Injection
("push" configuration) to configure application objects through setters
or constructors, rather than use any form of "pull" configuration like a
BeanFactory lookup. Spring's Dependency Injection functionality is
implemented using this BeanFactory interface and its subinterfaces.

相比诸如 BeanFactory 中查找的pull配置方式,通过setters或者构造方法,依赖注入的方式配置应用对象更好.Spring的依赖注入功能就是通过实现BeanFactory和其子接口实现的.

Normally a BeanFactory will load bean definitions stored in a configuration
source (such as an XML document), and use the {@code org.springframework.beans}
package to configure the beans. However, an implementation could simply return
Java objects it creates as necessary directly in Java code. There are no
constraints on how the definitions could be stored: LDAP, RDBMS, XML,
properties file, etc. Implementations are encouraged to support references
amongst beans (Dependency Injection).

通常,一个BeanFactory会从配置源(如X​​ML文件)中加载bena 定义,并使用{@code org.springframework.beans}包解析bean。然而,实现可以简单地返回Java代码直接新建的Java对象。这里没有限制bean 定义文件的格式:LDAP,RDBMS,XML.实现类欢迎支持应用而非bean(依赖注入)

In contrast to the methods in {@link ListableBeanFactory}, all of the
operations in this interface will also check parent factories if this is a
{@link HierarchicalBeanFactory}. If a bean is not found in this factory instance,
the immediate parent factory will be asked. Beans in this factory instance
are supposed to override beans of the same name in any parent factory.

对比{@link ListableBeanFactory}中的方法,如果这是一个{@link HierarchicalBeanFactory},这个接口的全部实现都会查找父工厂.如果在这个工厂实例找不到bean,去直接父工厂查找。factory实例中的bean会覆盖父factory实例中的同名bean。

Bean factory implementations should support the standard bean lifecycle interfaces
as far as possible. The full set of initialization methods and their standard order is:
bean factory 实现类应该尽量支持标准bean的生命周期接口.全套的初始化方法,已经排序如下

感觉这坨概念得好好理理
1. BeanNameAware's {@code setBeanName}
2. BeanClassLoaderAware's {@code setBeanClassLoader}
3. BeanFactoryAware's {@code setBeanFactory}
4. ResourceLoaderAware's {@code setResourceLoader}
(only applicable when running in an application context)
5. ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
(only applicable when running in an application context)
6. MessageSourceAware's {@code setMessageSource}
(only applicable when running in an application context)
7. ApplicationContextAware's {@code setApplicationContext}
(only applicable when running in an application context)
8. ServletContextAware's {@code setServletContext}
(only applicable when running in a web application context)
9. {@code postProcessBeforeInitialization} methods of BeanPostProcessors
10. InitializingBean's {@code afterPropertiesSet}
11. a custom init-method definition
12. {@code postProcessAfterInitialization} methods of BeanPostProcessors

On shutdown of a bean factory, the following lifecycle methods apply:
1. DisposableBean's {@code destroy}
2. a custom destroy-method definition

 package org.springframework.beans.factory;
public interface BeanFactory { /**
* 用于区分是否直接获取FactoryBean实例.
* bean以&开头表示获取FactoryBean实例.否则获取created的实例.For example, if the bean named
* {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
* will return the factory, not the instance returned by the factory.
*/
String FACTORY_BEAN_PREFIX = "&"; /**
* 返回一个原型或者单例实例.
* 抢单例,原型设计模式的饭碗
* 可以根据别名查找,也可以去父容器实例查找
*/
Object getBean(String name) throws BeansException; /**
* 加个类型
*/
<T> T getBean(String name, Class<T> requiredType) throws BeansException; /**
* 根据类型获取bean实例.可以是接口或子类,但不能是{@code null}.
* {@link ListableBeanFactory}也可以使用类型转化为name进行查找.更多bean集合的操作可以看
* ListableBeanFactory和BeanFactoryUtils
*/
<T> T getBean(Class<T> requiredType) throws BeansException; /**
* 多了构造方法,工厂方法的参数
*/
Object getBean(String name, Object... args) throws BeansException; /**
* 判断是否包含bean(包括别名,父容器)
* 陷阱出现:这边不管类是否抽象类,懒加载,是否在容器范围内,只要符合都返回true,所以这边true,不一定能从getBean获取实例
*/
boolean containsBean(String name); /**
* 是否单例
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException; /**
* 是否原型
*/
boolean isPrototype(String name) throws NoSuchBeanDefinitionException; /**
* 是否有跟name匹配类型的bean
*/
boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException; /**
* 根据bean name获取类型
*/
Class<?> getType(String name) throws NoSuchBeanDefinitionException; /**
* 获取别名
*/
String[] getAliases(String name); }