Spring ApplicationContext 体系结构


 

使用的spring源码版本 5.2.15.RELEASE
 

ApplicationContext体系结构图

在这里插入图片描述

 

白色的是接口,浅黄色的是实现类(包括抽象类)。

ApplicationContext 的实现种类很多,基于xml配置的、注解配置的上下文,基于Servlet、Reactive的web应用上下文,图中只列出了常见的实现类。

 

高级容器的常见接口、类

在高级容器的接口中,ConfigurableApplicationContext

  • 集成了高级容器通用的接口,功能齐全
  • 高级容器的实现类都实现了此接口,都是在此接口的基础上实现的
  • 要声明|使用高级容器的接口时,一般都是使用此接口,比如springboot声明使用的高级容器就是 ConfigurableApplicationContext 。
     

在高级容器的抽象实现类中,AbstractApplicationContext

  • 是 ConfigurableApplicationContext 接口的直接实现类,实现了 refresh()、getBean() 2个核心方法
  • 是高级容器所有实现类的基类,不管是基于xml配置文件还是注解配置,不管是基于servlet的spring mvc应用,还是基于reactive的 spring webflux应用,都是在 AbstractApplicationContext 的基础上实现的。
  • 声明|使用高级容器的抽象实现时,一般使用此抽象类
     

高级容器在接口层面通常指的是 ConfigurableApplicationContext,在抽象实现层面通常指的是 AbstractApplicationContext 。

 

高级容器常见的具体实现类如下

  • ClassPathXmlApplicationContext:根据classpath中的xml配置文件构建上下文。文件路径不用加前缀 classpath:,会自动加上。
  • FileSystemXmlApplicationContext:根据文件系统中的xml配置文件构建上下文。文件路径不用加前缀 file:,会自动加上。
  • AnnotationConfigApplicationContext:基于注解配置构建上下文
  • XmlWebApplicationContext:基于xml配置文件构建web上下文
  • AnnotationConfigWebApplicationContext:基于注解构建web上下文

最常用的是 ClassPathXmlApplicationContext

 

ResourceLoader 体系

ResourceLoader 加载指定资源

定义资源加载的通用操作

public interface ResourceLoader {

	//定义常量,classpath路径的前缀 classpath:
	String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;

	//加载指定位置的资源,解析为Resouce。一次只能加载一个资源
	Resource getResource(String location);

	//获取类加载器
	ClassLoader getClassLoader();

}

主要定义了getResource()方法,从指定位置加载资源,解析为Resouce。

 

ResourcePatternResolver 加载匹配的所有资源
public interface ResourcePatternResolver extends ResourceLoader {

	//定义常量,所有classpath路径的前缀
	String CLASSPATH_ALL_URL_PREFIX = "classpath*:";

	//从指定位置加载符合匹配的所有资源。eg. classpath*: application-*.yml,加载classpath中所有的application-*.yml文件
	Resource[] getResources(String locationPattern) throws IOException;

}

ResourcePatternResolver,重点是pattern,路径中可以使用通配符,匹配的资源都会被加载。

 

DefaultResourceLoader 默认实现类

给 ResourceLoader 接口提供默认实现。

 

Aware 体系

Aware 标记bean的一个顶级接口
public interface Aware {

}

aware 感知,是标记bean的一个顶级接口,在被标记的bean发生特定事件时,spring容器会以回调方法的形式调用Aware中的方法完成特定的功能。

实际使用的子接口一般只提供一个方法,返回值为void。

此处介绍常见的三个子接口。

 

BeanNameAware 设置beanName
public interface BeanNameAware extends Aware {

	void setBeanName(String name);

}

在创建bean实例时调用,设置实例的名称

 

BeanFactoryAware 设置BeanFactory
public interface BeanFactoryAware extends Aware {

	void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}

在创建bean实例时调用,设置创建bean实例时要使用的 BeanFactory 实例

 

BeanClassLoaderAware 设置BeanClassLoader
public interface BeanClassLoaderAware extends Aware {

	void setBeanClassLoader(ClassLoader classLoader);

}

在BeanFactory实例创建bean实例,加载bean对应的java类时,用于设置bean对应的java类的类加载器

 

ApplicationContextAware 应用上下文变化时的回调
public interface ApplicationContextAware extends Aware {

	void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}

ApplicationContext 变化时自动调用,常用于保存应用上下文的引用。

 

涉及的零散接口

EnvironmentCapable 获取环境
public interface EnvironmentCapable {

	//获取当前组件的环境
	Environment getEnvironment();

}

所谓环境,就是context 上下文,都是BeanFactory的实例。ApplicationContext实例一定是BeanFactory实例,但BeanFactory实例不一定是ApplicationContext实例。

EnvironmentCapable接口用于获取获取当前容器的环境,可以用来判断容器类型,判断上下文是ApplicationContext实例(高级容器),还是其它的BeanFactory实例(低级容器)。

 

MessageSource 国际化消息
public interface MessageSource {

	//获取地区对应的指定消息。code是消息代号,args是用于填充消息的实参数组
	String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);

	//找不到对应的消息时直接抛出异常
	String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;

	//支持自定义的消息解析策略
	String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;

}

MessageSource,顾名思义,指定来源的消息,来源是指国家地区、语言。

3个方法都有参数 locale 用于指定地区,会获取code对应消息的指定地区表示,示例

CHINESE:没有找到名字为{beanName}的bean

ENGLISH:The bean named {beanName} was not found

locale为CHINESE则返回对应的中文消息,为ENGLISH则返回对应的英文消息,并用args传入的实参替换占位符。

 

Closeable 关闭资源

这个是 java.io 中的接口,用于关闭资源

public interface Closeable extends AutoCloseable {

    public void close() throws IOException;
    
}

 

Lifecycle 生命周期控制

定义了控制容器生命周期的 start()、stop() 方法

public interface Lifecycle {

	void start();

	void stop();

	boolean isRunning();

}

 

InitializingBean 初始化bean实例
public interface InitializingBean {

	void afterPropertiesSet() throws Exception;

}

doCreateBean() 创建bean实例的主要过程:创建实例 -> 填充属性 -> 初始化。

初始化的过程:处理实现的Aware接口 -> 执行 BeanPostProcessor 的postProcessBeforeInitialization() 方法 -> 执行初始化方法 -> 执行 BeanPostProcessor 的postProcessAfterInitialization() 方法。

初始化方法有2种,依次为实现的 InitializingBean接口中 的 afterPropertiesSet() 方法、init-method 属性指定的初始化方法。

afterPropertiesSet() 顾名思义,是在属性设置完之后要执行的操作。填充属性阶段设置属性值,处理Aware阶段设置beanName、要使用的类加载器、BeanFactory实例,至此属性设置已完成,开始执行
afterPropertiesSet() 方法对bean实例进行加工修饰。

 

AnnotationConfigRegistry 注解配置bean
public interface AnnotationConfigRegistry {

	//注解组件
	void register(Class<?>... componentClasses);

	//扫描指定的包
	void scan(String... basePackages);

}

 

ApplicationContext 体系

ApplicationContext 高级容器的顶级父类
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

	//获取当前context的id,id唯一标识一个context(上下文)
	String getId();

	//获取当前context所属application的名称
	String getApplicationName();

	//获取当前context的显示名称(displayName比id友好)
	String getDisplayName();

	//获取当前context(注意不是application)第一次被loaded时的时间戳
	long getStartupDate();

	//获取父context,如果为null则表示当前context是根context
	ApplicationContext getParent();

	//获取当前context的AutowireCapableBeanFactory
	AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;

}

ApplicationContext 继承了6个接口,整合了这些接口的功能

  • BeanFactory的2个子接口:ListableBeanFactory、HierarchicalBeanFactory,可列单、分层
  • EnvironmentCapable 获取容器环境
  • MessageSource 国际化信息
  • ApplicationEventPublisher 应用事件
  • ResourcePatternResolver 资源的匹配加载

 

WebApplicationContext 提供对web的支持
public interface WebApplicationContext extends ApplicationContext {

	String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";

	//这3个作用域都是建立在标准作用域singleton、prototype的基础上
	String SCOPE_REQUEST = "request";
	String SCOPE_SESSION = "session";
	String SCOPE_APPLICATION = "application";

	String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
	String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
	String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";
	
	ServletContext getServletContext();

}

主要定义了web相关的作用域,以及获取servlet上下文的 getServletContext() 方法。

 

ConfigurableApplicationContext 提供高级容器的通用配置方法
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {

	//设置path时支持的分隔符
	String CONFIG_LOCATION_DELIMITERS = ",; \t\n";

	//配置相关的bean的name
	String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
	String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
	String ENVIRONMENT_BEAN_NAME = "environment";
	String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
	String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
	String APPLICATION_STARTUP_BEAN_NAME = "applicationStartup";


	String SHUTDOWN_HOOK_THREAD_NAME = "SpringContextShutdownHook";


	//设置 application context 的id
	void setId(String id);

	//设置 parent application context
	void setParent(@Nullable ApplicationContext parent);


	//Environment
	void setEnvironment(ConfigurableEnvironment environment);
	ConfigurableEnvironment getEnvironment();


	//ApplicationStartup
	void setApplicationStartup(ApplicationStartup applicationStartup);
	ApplicationStartup getApplicationStartup();


	//添加 BeanFactoryPostProcessor
	void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);

	//添加应用事件监听器 ApplicationListener
	void addApplicationListener(ApplicationListener<?> listener);

	//设置类加载器,用于加载classpath中的资源、bean对应的java类
	void setClassLoader(ClassLoader classLoader);

	//添加资源协议解析器。资源协议指的 classpath:、file: 等,规定资源的来源类型
	void addProtocolResolver(ProtocolResolver resolver);

	/**
	 * 加载|刷新配置。这个方法用于启动容器,并在启动时根据配置实例化单例。
	 * 如果启动失败应该销毁所有已经创建好的单例,即要么启动成功所有单例都实例化,要么启动失败所有单例都没有实例化
	 */
	void refresh() throws BeansException, IllegalStateException;

	//注册jvm runtime的shutdown钩子,在jvm shutdown时自动关闭当前context
	void registerShutdownHook();

	/**
	 * 关闭当前容器(application context),释放资源。
	 * 只是关闭当前应用上下文,不会关闭 parent context,父上下文有它们自己的生命周期。
	 */
	@Override
	void close();

	/**
	 * 判断当前 application context 是否是活动状态,常用于判断容器是否可用。
	 * 至少调用过一次 refresh(),且尚未调用 close() 进行关闭,则为 active 状态
	 */
	boolean isActive();

	//获取内部低级容器对应的 ConfigurableListableBeanFactory 实例
	ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

}

ConfigurableApplicationContext 继承了 ApplicationContext、Lifecycle、Closeable 3个接口,主要

  • 定义了配置高级容器的常用方法,比如设置父容器、Environment、类加载器,添加BeanFactoryPostProcessor、ApplicationListener、资源协议解析器,以及获取内部低级容器对应的 ConfigurableListableBeanFactory 实例
  • 集成了容器的生命周期控制,定义了容器生命周期中常用的 refresh()、close()方法

 

AbstractApplicationContext 提供高级容器的基本实现

源码主要内容如下

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {

	//定义了一些beanName
	public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";
	public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";
	public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";


	//---------------------------------------------------------------------
	// Implementation of ApplicationContext interface
	//---------------------------------------------------------------------

	@Override
	public void setId(String id) {
		//...
	}

	@Override
	public String getId() {
		//...
	}

	@Override
	public String getApplicationName() {
		//...
	}

	@Override
	public String getDisplayName() {
		//...
	}

	@Override
	@Nullable
	public ApplicationContext getParent() {
		//...
	}

	@Override
	public void setEnvironment(ConfigurableEnvironment environment) {
		//...
	}
	
	@Override
	public ConfigurableEnvironment getEnvironment() {
		//...
	}

	@Override
	public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
		//...
	}

	/**
	 * Return the timestamp (ms) when this context was first loaded.
	 */
	@Override
	public long getStartupDate() {
		//...
	}

	@Override
	public void publishEvent(ApplicationEvent event) {
		//...
	}

	@Override
	public void publishEvent(Object event) {
		//...
	}

	@Override
	public void setApplicationStartup(ApplicationStartup applicationStartup) {
		//...
	}

	@Override
	public ApplicationStartup getApplicationStartup() {
		//...
	}


	//---------------------------------------------------------------------
	// Implementation of ConfigurableApplicationContext interface
	//---------------------------------------------------------------------
	
	@Override
	public void setParent(@Nullable ApplicationContext parent) {
		//...
	}

	@Override
	public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
		//...
	}

	@Override
	public void addApplicationListener(ApplicationListener<?> listener) {
			//...
	}

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		//...
	}

	@Override
	public void registerShutdownHook() {
		//...
	}

	@Override
	public void close() {
		//...
	}

	@Override
	public boolean isActive() {
		//...
	}


	//---------------------------------------------------------------------
	// Implementation of BeanFactory interface
	//---------------------------------------------------------------------

	@Override
	public Object getBean(String name) throws BeansException {
		//...
	}

	@Override
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		//...
	}

	@Override
	public Object getBean(String name, Object... args) throws BeansException {
		//...
	}

	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		//...
	}

	@Override
	public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
		//...
	}

	@Override
	public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {
		//...
	}

	@Override
	public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
		//...
	}

	@Override
	public boolean containsBean(String name) {
		//...
	}

	@Override
	public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
		//...
	}

	@Override
	public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
		//...
	}

	@Override
	public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
		//...
	}

	@Override
	public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
		//...
	}

	@Override
	@Nullable
	public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
		//...
	}

	@Override
	@Nullable
	public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
		//...
	}

	@Override
	public String[] getAliases(String name) {
		//...
	}


	//---------------------------------------------------------------------
	// Implementation of ListableBeanFactory interface
	//---------------------------------------------------------------------

	@Override
	public boolean containsBeanDefinition(String beanName) {
		//...
	}

	@Override
	public int getBeanDefinitionCount() {
		//...
	}

	@Override
	public String[] getBeanDefinitionNames() {
		//...
	}

	@Override
	public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit) {
		//...
	}

	@Override
	public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType, boolean allowEagerInit) {
		//...
	}

	@Override
	public String[] getBeanNamesForType(ResolvableType type) {
		//...
	}

	@Override
	public String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
		//...
	}

	@Override
	public String[] getBeanNamesForType(@Nullable Class<?> type) {
		//...
	}

	@Override
	public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
		//...
	}

	@Override
	public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException {
		//...
	}

	@Override
	public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
			throws BeansException {
		//...
	}

	@Override
	public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) {
		//...
	}

	@Override
	public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
			throws BeansException {
		//...
	}

	@Override
	@Nullable
	public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
			throws NoSuchBeanDefinitionException {
		//...
	}


	//---------------------------------------------------------------------
	// Implementation of HierarchicalBeanFactory interface
	//---------------------------------------------------------------------

	@Override
	@Nullable
	public BeanFactory getParentBeanFactory() {
		//...
	}


	//---------------------------------------------------------------------
	// Implementation of MessageSource interface
	//---------------------------------------------------------------------

	@Override
	public String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) {
		//...
	}

	@Override
	public String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException {
		//...
	}

	@Override
	public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
		//...
	}
	

	//---------------------------------------------------------------------
	// Implementation of ResourcePatternResolver interface
	//---------------------------------------------------------------------

	@Override
	public Resource[] getResources(String locationPattern) throws IOException {
		//...
	}


	//---------------------------------------------------------------------
	// Implementation of Lifecycle interface
	//---------------------------------------------------------------------

	@Override
	public void start() {
		//...
	}

	@Override
	public void stop() {
		//...
	}

	@Override
	public boolean isRunning() {
		//...
	}


	//---------------------------------------------------------------------
	// Abstract methods that must be implemented by subclasses
	//---------------------------------------------------------------------

	protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;

	protected abstract void closeBeanFactory();

	@Override
	public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

}

AbstractApplicationContext 这个抽象类给多个接口提供了大量的方法实现,比如实现了事件发布、国际化消息、资源加载、容器的通用配置方法、容器的生命周期方法等,实现了高级容器的基本功能。重点关注实现的2个核心方法:getBean()获取bean实例、refresh()加载|刷新配置,getBean()实质是调用内置低级容器对应的方法。

此外,AbstractApplicationContext 还规定了子类必须要实现的方法,这3个方法都在子类 AbstractRefreshableApplicationContext 中实现了。

 

AbstractRefreshableApplicationContext 完善容器的 refresh 功能

核心代码内容如下

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

	//是否允许bean定义覆盖
	private Boolean allowBeanDefinitionOverriding;
	
	//是否允许循环依赖
	private Boolean allowCircularReferences;
	
	//内置的低级容器实例
	private volatile DefaultListableBeanFactory beanFactory;

	public AbstractRefreshableApplicationContext() {
	}
	
	public AbstractRefreshableApplicationContext(@Nullable ApplicationContext parent) {
		super(parent);
	}

	public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
		this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
	}

	public void setAllowCircularReferences(boolean allowCircularReferences) {
		this.allowCircularReferences = allowCircularReferences;
	}
	
	@Override
	protected final void refreshBeanFactory() throws BeansException {
		//...
	}

	@Override
	protected void cancelRefresh(BeansException ex) {
		//...
	}

	@Override
	protected final void closeBeanFactory() {
		//...
	}

	@Override
	public final ConfigurableListableBeanFactory getBeanFactory() {
		//...
	}

	@Override
	protected void assertBeanFactoryActive() {
	}

}

AbstractRefreshableApplicationContext 是在 AbstractApplicationContext 的基础上进行完善,主要做了2件事

  • 提供了是否允许bean定义覆盖、循环依赖的配置,以及内置低级容器的创建、设置(在refresh相关的几个方法中)
  • 完善refresh相关方法。AbstractApplicationContext 实现了 refresh() 方法,refresh()是刷新整个高级容器,其中包括操作内置低级容器的很多操作,这些操作在 AbstractApplicationContext 中被定义为 protected() 方法,尚未提供实现,AbstractRefreshableApplicationContext 给这些方法提供了实现,完善了容器的刷新功能。

 

AbstractRefreshableConfigApplicationContext 提供对配置文件的支持
public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext
		implements BeanNameAware, InitializingBean {

	//配置文件位置
	private String[] configLocations;

	private boolean setIdCalled = false;

	public AbstractRefreshableConfigApplicationContext() {
	}
	
	public AbstractRefreshableConfigApplicationContext(@Nullable ApplicationContext parent) {
		super(parent);
	}

	public void setConfigLocation(String location) {
		//...
	}
	
	public void setConfigLocations(@Nullable String... locations) {
		//...
	}

	protected String[] getConfigLocations() {
		//...
	}

	protected String[] getDefaultConfigLocations() {
		//...
	}

	protected String resolvePath(String path) {
		return getEnvironment().resolveRequiredPlaceholders(path);
	}


	@Override
	public void setId(String id) {
		//...
	}

	@Override
	public void setBeanName(String name) {
		//...
	}
	
	//加载|刷新配置
	@Override
	public void afterPropertiesSet() {
		if (!isActive()) {
			refresh();
		}
	}

}

这个类主要提供了配置文件位置的相关方法,支持文件方式的配置,是所有基于文件进行配置的基类。

和 springboot 不同,spring默认的配置文件位置是null,即没有默认的配置文件位置。

 

AbstractXmlApplicationContext 提供对xml配置文件的支持

核心源码如下

public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {

	/**
	 * 从xml配置文件中加载、解析配置,获取 BeanDefinition
	 */
	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		loadBeanDefinitions(beanDefinitionReader);
	}

	@Nullable
	protected Resource[] getConfigResources() {
		return null;
	}

}

主要实现了 loadBeanDefinitions() 方法,可以从xml配置文件中加载、解析配置,得到 BeanDefinition。

 

ClassPathXmlApplicationContext、FileSystemXmlApplicationContext 从classpath|文件系统中加载配置文件

这2个类的代码很相似,以 ClassPathXmlApplicationContext 为例,核心构造方法如下


/**
 * @param configLocations 指定配置文件位置
 * @param refresh 是否调用refresh()加载|刷新配置
 * @param parent 父上下文,可以为null
 */
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
	super(parent);
	setConfigLocations(configLocations);
	if (refresh) {
		refresh();
	}
}

其它构造方法都是调用这个构造方法,参数指定配置文件位置,设置配置文件的位置,然后 refresh() 加载|刷新配置。参数refresh一般都是true。

 

GenericApplicationContext 提供高级容器的通用实现

 

AnnotationConfigApplicationContext 提供对注解配置的支持

核心代码如下

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

	//核心构造方法
	public AnnotationConfigApplicationContext(String... basePackages) {
		this();
		//扫描指定的包,注册扫描到的组件
		scan(basePackages);
		//加载|刷新配置,使配置生效
		refresh();
	}

	//设置beanName
	public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
		this.reader.setBeanNameGenerator(beanNameGenerator);
		this.scanner.setBeanNameGenerator(beanNameGenerator);
		//注册单例
		getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
	}

}

可以关注下 BeanNameGenerator 接口,这个接口定义了beanName的生成方式,在xml、注解配置方式中都用到了。

 

spring中配置bean的2种方式

从以上介绍不难看出有2种配置bean的方式:xml配置文件、注解配置。
 

注解配置

@Configuration
public class SysConfig {

    @Bean
    public A getA() {
        return new A();
    }

    @Bean
    public B getB() {
        return new B();
    }

}
@Controller
public class UserController {

    @Autowired
    private UserService userService;

}

@Configuration、@Controller 之类把类标注为bean的注解,实质都是在 @Component 的基础上实现的,把类作为组件注册为spring容器中的bean。

@Bean 可以把方法返回的对象作为bean放到容器中。

 

对应的创建方式

//参数指定配置文件位置
ClassPathXmlApplicationContext applicationContext1 = new ClassPathXmlApplicationContext("spring.xml");
ClassPathXmlApplicationContext applicationContext2 = new ClassPathXmlApplicationContext("spring-bean.xml", "spring-log4j.xml");

//参数指定要扫描的包
AnnotationConfigApplicationContext applicationContext3 = new AnnotationConfigApplicationContext("com.chy.mall");
AnnotationConfigApplicationContext applicationContext4 = new AnnotationConfigApplicationContext("com.chy.mall.admin", "com.chy.mall.support");

参数个数都可变,都支持模块化配置,可用 import 标签或者注解导入其它配置。

 

说明

许多博文分得更细,说是3种配置方式,也行

  • xml配置文件
  • @Autowired之类自动装配的注解
  • @Controller、@Configuration、@Bean之类标注bean的注解
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值