BeanFactory和ApplicationContext

BeanFactory

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

这个接口是由包含许多bean定义的对象实现的,每个定义都由一个字符串名唯一标识。根据bean定义,工厂将返回所包含对象的独立实例(Prototype 原型设计模式)或单个共享实例(比单例设计模式更好的选择,一个工厂范围内的单例实例)。返回哪种类型的实例取决于bean工厂配置: API是相同的。从Spring 2.0开始,根据具体的应用程序上下文(例如,“request”和“session”适用于web环境)。

此方法的要点是BeanFactory是应用程序组件的中心注册表,并集中配置应用程序组件(例如,不再需要单个对象读取属性文件)。请参阅“专家一对一的J2EE设计和开发”的第4章和第11章,以讨论这种方法的好处。

注意,通常依靠通过setter或构造函数配置的方式使用依赖注入(“push”配置)配置应用程序对象是更好的方法 ,而不是使用任何形式的“pull”配置,如BeanFactory查找。Spring的依赖注入功能是使用这个BeanFactory接口及其子接口实现的。

三种注入方式:field注入,setter注入,构造器注入;
都需要使用@Autowired;
field注入最终通过反射来设置属性值
构造函数早于field注入执行。

通常,BeanFactory将加载存储在配置源(例如XML文档)中的bean定义,并使用{@code org.springframework.bean}包来配置bean。但是,实现可以简单地返回它在Java代码中直接创建的Java对象。定义的存储方式没有限制:LDAP、RDBMS、XML、属性文件等等。鼓励实现支持bean之间的引用(依赖注入)。

与{@link ListableBeanFactory}中的方法相比,这个接口中的所有操作也将检查父工厂,如果这是一个{@link HierarchicalBeanFactory}。如果在这个工厂实例中没有找到bean,将会询问直接的父工厂。这个工厂实例中的bean应该覆盖任何父工厂中同名的bean。

Bean工厂实现应该尽可能支持标准Bean生命周期接口。初始化方法的完整集合及其标准顺序为:

* <ol>
* <li>BeanNameAware’s {@code setBeanName}
* <li>BeanClassLoaderAware’s {@code setBeanClassLoader}
* <li>BeanFactoryAware’s {@code setBeanFactory}
* <li>EnvironmentAware’s {@code setEnvironment}
* <li>EmbeddedValueResolverAware’s {@code setEmbeddedValueResolver}
* <li>ResourceLoaderAware’s {@code setResourceLoader}
* (only applicable when running in an application context)
* <li>ApplicationEventPublisherAware’s {@code setApplicationEventPublisher}
* (only applicable when running in an application context)
* <li>MessageSourceAware’s {@code setMessageSource}
* (only applicable when running in an application context)
* <li>ApplicationContextAware’s {@code setApplicationContext}
* (only applicable when running in an application context)
* <li>ServletContextAware’s {@code setServletContext}
* (only applicable when running in a web application context)
* <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
* <li>InitializingBean’s {@code afterPropertiesSet}
* <li>a custom init-method definition
* <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
* </ol>

方法

String FACTORY_BEAN_PREFIX = "&"; 如果BeanName添加前缀”&”,那么使用这个BeanName获得的Bean实例是其所在FactoryBean的实例,也就是实现 FactoryBean 接口的那个类的Bean实例。

getType: 检查具有给定名称的bean是否与指定的类型匹配。更具体地说,检查给定beanName调用{@link #getBean} 是否会返回对象,这个对象可分配给指定目标类型。<p>将别名转换回相应的规范bean名称。 在此工厂实例中找不到bean 将询问父工厂()。

重点是getBean()方法:获得Bean

DefaultListableBeanFactory

AliasRegistry:注册别名用的

singletonBeanRegistry 注册单例Bean用的

ListableBeanFactory

这个接口的作用就是用以枚举所有Bean

Extension of the {@link BeanFactory} interface to be implemented by bean factories that can enumerate all their bean instances, rather than attempting bean lookup by name one by one as requested by clients. BeanFactory implementations that preload all their bean definitions (such as XML-based factories) may implement this interface.

扩展{@link BeanFactory}接口,由能够枚举所有bean实例的bean工厂实现,而不是按照客户机的请求逐个尝试bean查找。预加载所有bean定义(如基于xml的工厂)的BeanFactory实现可以实现此接口。

HierarchicalBeanFactory

就两个方法,getParentBeanFactory,containsLocalBean

子接口由bean工厂实现,可以是层次结构的一部分。<p>在ConfigurableBeanFactory接口中可以找到bean工厂对应的{@code setParentBeanFactory}方法,该方法允许以可配置的方式设置父类。

ConfigurableBeanFactory

大多数bean工厂要实现的配置接口。提供配置bean工厂的工具,以及在{@link org.springframework.bean.factory.BeanFactory }中的bean工厂客户端方法接口。

<p>这个bean工厂接口不适合在普通的应用程序代码中使用: 对于典型的需求坚持使用{@link org.springframework.beans.factory.BeanFactory}或者{@link org.springframework.beans.factory.ListableBeanFactory}。这个扩展接口只是为了允许框架-内部即插即用以及对bean工厂配置方法的特殊访问

什么叫 允许框架-内部即插使用,比如ConfigurableBeanFactory接口中有一个方法:void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

AutowireCapableBeanFactory: 能够自动装配的bean工厂

createBean(Class<T> beanClass)

autowireBean(Object existingBean)

configureBean(Object existingBean, String beanName)

applyBeanPropertyValues(Object existingBean, String beanName)

initializeBean(Object existingBean, String beanName)

applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)

applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)

BeanDefinitionRegistry

用于保存bean定义的注册中心的接口 ,一些对BeanDefinition的基础操作,增删改查验证什么的

DefaultListableBeanFactory:具体继承了一个抽象类,两个接口

ApplicationContext

总览

找一个例子开始,看看Spring是怎么构建一个容器的。

所以AbstractRefreshableConfigApplicationContext 这个接口 作为一个节点,从这开始来看一下。

追根溯源发现,依次是:
C:AbstractRefreshableConfigApplicationContext >
C:AbstractRefreshableApplicationContext >
C:AbstractApplicationContext >
I:ConfigurableApplicationContext >
I:ApplicationContext

那么来看一下:

ApplicationContext

为应用程序提供配置的中心接口。在应用程序运行时,这是只读的,但如果实现接口的类支持,则可以重新加载。

ApplicationContext 是Spring应用容器的顶级接口,提供BeanFactory来访问应用的组件; 以通用方式加载文件资源的能力(Resource) ; 将事件发布到已注册侦听器的能力(publisherEvent); 解析消息的能力,支持国际化 (Message);

EnvironmentCapable接口:ApplicationContext的实现,在ConfigurableApplicationContext中重写了接口方法 getEnvironment()
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
getId
getApplicationName
getDisplayName
getStartupDate
getParent
getAutowireCapableBeanFactory
}

ConfigurableApplicationContext

<p>配置和生命周期方法封装在这里,以避免使他们明显的ApplicationContext客户端代码。目前的方法只能在启动和关闭代码中使用。

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
    setId
    setParent
    setEnvironment
    getEnvironment
    addBeanFactoryPostProcessor
    addApplicationListener :事件相关监听器
    addProtocolResolver :添加不同协议的资源解析器
    refresh
    registerShutdownHook
    close
    isActive
    getBeanFactory
}

setEnvironment,getEnvironment:添加了setEnvironment方法,且把getEnvironment重写了,添加了固定的返回值类型ConfigurableEnvironment,缩小了返回值的签名(范围,narrows the signature

refresh:加载或刷新配置的持久表示,它可以是XML文件、属性文件或关系数据库模式。由于这是一种启动方法,如果失败,它应该销毁已经创建的单例,以避免悬挂资源。换句话说,在调用该方法之后,应该实例化所有(启动成功)或根本不实例化单例(启动失败)

registerShutdownHook:Register a shutdown hook with the JVM runtime,JVM运行时注册的一个关闭的钩子。触发则关闭容器

close:Close this application context, releasing all resources and locks that the implementation might hold. This includes destroying all cached singleton beans.

isActive:whether it has been refreshed at least once and has not been closed yet@return whether the context is still active,如果容器已经refresh过一次且没有close过,那么就是active的状态

addBeanFactoryPostProcessor:
Add a new BeanFactoryPostProcessor that will get applied to the internal
* bean factory of this application context on refresh, before any of the
* bean definitions get evaluated. To be invoked during context configuration.

给BeanFactory添加一个 BeanFactoryPostProcessor ,在 配置上下文也就是配置容器的时候被调用,也就是调用refresh()的时候

ConfigurableListableBeanFactory getBeanFactory() :Return the internal bean factory of this application context. 获取一个容器保存再内部的BeanFactory,不过必须是初始化好的也就是在容器的状态为active的时候才可以调用这个方法获取BeanFactory。

AbstractApplicationContext

抽象实现,但是基本的方法都已经实现了,比如最重要的refresh

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

AbstractRefreshableApplicationContext

AbstractRefreshableConfigApplicationContext





除非注明,否则均为一叶呼呼原创文章,转载必须以链接形式标明本文链接

本文链接:http://www.yiyehu.tech/archives/2020/05/28/beanfactory-and-applicationcontext

发表评论

电子邮件地址不会被公开。 必填项已用*标注