一、Application整体继承关系
image.pngApplicationContext的子接口分为两个部分:
- ConfigurableApplicationContext:大部分的应用上下文都实现了该接口
- WebApplicationContext:在web应用程序中使用
二、ConfigurableApplicationContext方法
ConfigurableApplicationContext
中的方法:
void setId(String id); // 设置应用上下文唯一的id
void setParent(ApplicationContext parent); // 设置应用程序上下文的父级
void setEnvironment(ConfigurableEnvironment environment); // 设置应用上下文的环境
ConfigurableEnvironment getEnvironment(); // 获取应用上下文的环境
// 添加一个新的BeanFactoryPostProcessor
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
// 添加应用程序监听器
void addApplicationListener(ApplicationListener<?> listener);
// 添加协议解析器,可能会覆盖默认的规则
void addProtocolResolver(ProtocolResolver resolver);
// 加载或者刷新配置
void refresh() throws BeansException, IllegalStateException;
// 向JVM runtime注册一个关闭钩子,JVM关闭时关闭这个上下文
void registerShutdownHook();
// 应用程序上问下是否是激活状态
boolean isActive();
// 获取应用上下文内部的bean factory
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
这里面比较重要的就是refresh方法,这个refresh会被子类重写,主要用来做容器加载bean的主要流程。
2.1 AbstractApplicationContext
AbstractApplicationContext是ApplicationContext接口的抽象实现,里面用到了模板方法模式,把需要子类实现的方法通过重新定义抽象方法的方式暴露出去。
AbstractApplicationContext中重新定义的抽象方法
// 刷新BeanFactory,用于执行实际的配置加载,该方法在其他的初始化工作之前被refresh()方法调用
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
// 关闭BeanFactory,用于释放内部使用的BeanFactory·
protected abstract void closeBeanFactory();
// 获取内部使用的BeanFactory
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
2.2 GenericApplicationContext
GenericApplicationContext继承自AbstractApplicationContext,能够加载xml/properties等文件,内部持有一个DefaultListableBeanFactory的实例。这里能够加载xml、properties文件是因为GenericApplicationContext实现了BeanDefinitionRegistry接口,需要借助外部XmlBeanDefinitionReader的方法来把BeanDefinition注册到bean工厂中。常见的使用方法:
GenericApplicationContext ctx = new GenericApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
PropertiesBeanDefinitionReader propReader = new PropertiesBeanDefinitionReader(ctx);
propReader.loadBeanDefinitions(new ClassPathResource("otherBeans.properties"));
ctx.refresh();
MyBean myBean = (MyBean) ctx.getBean("myBean");
2.3 GenericXmlApplicationContext
从上面的GenericApplicationContext的执行流程可以推断出来,GenericXmlApplicationContext内部应该是用XmlBeanDefinitionReader做了配置文件的解析,可以看下XmlBeanDefinitionReader的代码:
public GenericXmlApplicationContext(Resource... resources) {
load(resources);
refresh();
}
/**
* Create a new GenericXmlApplicationContext, loading bean definitions
* from the given resource locations and automatically refreshing the context.
* @param resourceLocations the resources to load from
*/
public GenericXmlApplicationContext(String... resourceLocations) {
load(resourceLocations);
refresh();
}
2.4 AnnotationConfigApplicationContext
AnnotationConfigApplicationContext继承自GenericApplicationContext,提供了注解配置(例如:Configuration、Component、inject等)和类路径扫描(scan方法)的支持,可以使用register(Class<?>... annotatedClasses)来注册一个一个的进行注册。
2.5 AbstractRefreshableApplicationContext
AbstractRefreshableApplicationContext继承自AbstractApplicationContext,支持多次进行刷新(多次调用refresh方法),每次刷新时在内部创建一个新的bean工厂的实例。子类仅仅需要实现loadBeanDefinitions方法,该方法在每次刷新时都会调用。
2.6 AbstractRefreshableConfigApplicationContext
AbstractRefreshableConfigApplicationContext继承自AbstractRefreshableApplicationContext,添加了对指定的配置文件路径的公共的处理,可以把他看作基于XML的应用上下文的基类。实现了如下的两个接口:
- BeanNameAware用于设置上下文的bean的名称,只有一个方法:void setBeanName(String name)
- InitializingBean用于上下文一切就绪后,如果还未刷新,那么就执行刷新操作,只有一个方法:void afterPropertiesSet()
2.7 AbstractXmlApplicationContext
AbstractXmlApplicationContext继承AbstractRefreshableConfigApplicationContext,里面是有一个XmlBeanDefinitionReader来对加载的配置文件进行处理。
2.8 FileSystemXmlApplicationContext
FileSystemXmlApplicationContext继承自AbstractXmlApplicationContext,用来解析文件系统中的xml配置文件。
@Override
protected Resource getResourceByPath(String path) {
if (path.startsWith("/")) {
path = path.substring(1);
}
return new FileSystemResource(path);
}
2.9 ClassPathXmlApplicationContext
ClassPathXmlApplicationContext继承自AbstractXmlApplicationContext,和FileSystemXmlApplicationContext类似,只不过ClassPathXmlApplicationContext是用于处理类路径下的XML配置文件。
3 WebApplicationContext
该接口提供了在web应用中的配置,接口提供了一个ServletContext getServletContext()用来获取ServletContext对象。该接口会和ServletContext的一个属性进行绑定,这个属性就是ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE。
@Nullable
ServletContext getServletContext();
3.1 ConfigurableWebApplicationContext
ConfigurableWebApplicationContext继承自WebApplicationContext和ConfigurableApplicationContext,提供了web应用上下文的可配置的能力。
// 设置web应用上下文的ServletContext
void setServletContext(@Nullable ServletContext servletContext);
// 设置web应用上下文的ServletConfig
void setServletConfig(@Nullable ServletConfig servletConfig);
// 获取web应用上下文的ServletConfig
ServletConfig getServletConfig();
// 设置web应用上下文的命名空间
void setNamespace(@Nullable String namespace);
// 获取web应用上下文的命名空间
String getNamespace();
// 以初始化参数的形式设置web应用上下文的配置文件位置
void setConfigLocation(String configLocation);
// 设置web应用上下文的配置文件的位置
void setConfigLocations(String... configLocations);
// 获取web应用上下文的配置文件位置
String[] getConfigLocations();
这种在顶级接口里面只设置了获取的方法,然后在子接口里面去定义设置方法,也是比较常见的做法。
3.2 GenericWebApplicationContext
GenericWebApplicationContext继承自GenericApplicationContext,实现了ConfigurableWebApplicationContext和ThemeSource接口。该类设计的目的不是在web.xml中进行声明式的安装,而是编程式的安装,例如使用WebApplicationInitializers来构建内嵌的上下文。该接口在ConfigurableWebApplicationContext的内容都是一个伪实现,调用其中的大多数方法都会抛出异常。
3.3 AbstractRefreshableWebApplicationContext
GenericWebApplicationContext继承自AbstractRefreshableConfigApplicationContext,实现了ConfigurableWebApplicationContext和ThemeSource接口,主要是用于web环境下。在web程序启动的时候,提供一个configLocations属性,通过ConfigurableWebApplicationContext接口来进行填充。子类化这个接口是很简单的,所有你所需要做的事情就是实现loadBeanDefinitions方法,来实现你自己的bean定义的加载逻辑。
3.4 XmlWebApplicationContext
XmlWebApplicationContext继承自AbstractRefreshableWebApplicationContext,接受能被XmlBeanDefinitionReader所理解的XML文档配置。对于根上下文,默认的配置文件路径是/WEB-INF/applicationContext.xml,对于命名空间为test-servlet的上下文,默认的配置文件路径是/WEB-INF/test-servlet.xml
默认的配置路径代码:
protected String[] getDefaultConfigLocations() {
return this.getNamespace() != null ? new String[]{"/WEB-INF/" + this.getNamespace() + ".xml"} : new String[]{"/WEB-INF/applicationContext.xml"};
}
3.5 AnnotationConfigWebApplicationContext
AnnotationConfigWebApplicationContext继承自AbstractRefreshableWebApplicationContext,接受注解的类作为输入,允许一个一个的注入,同样也能使用类路径扫描,使用方法和AnnotationConfigApplicationContext一样。
网友评论