目录
- ApplicationContext体系结构图
- 高级容器的常见接口、类
- ResourceLoader 体系
- Aware 体系
- 涉及的零散接口
- ApplicationContext 体系
- ApplicationContext 高级容器的顶级父类
- WebApplicationContext 提供对web的支持
- ConfigurableApplicationContext 提供高级容器的通用配置方法
- AbstractApplicationContext 提供高级容器的基本实现
- AbstractRefreshableApplicationContext 完善容器的 refresh 功能
- AbstractRefreshableConfigApplicationContext 提供对配置文件的支持
- AbstractXmlApplicationContext 提供对xml配置文件的支持
- ClassPathXmlApplicationContext、FileSystemXmlApplicationContext 从classpath|文件系统中加载配置文件
- GenericApplicationContext 提供高级容器的通用实现
- AnnotationConfigApplicationContext 提供对注解配置的支持
- spring中配置bean的2种方式
使用的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的注解