Spring IOC-ApplicationContext的继承关系
来源:互联网 发布:电视台直播软件 编辑:程序博客网 时间:2024/05/22 13:49
前面的文章Spring IOC-BeanFactory的继承体系分享了BeanFactory的所有接口,抽象类以及实现类的主要方法及层级关系。今天我们分享BeanFactory的相当于一个分支ApplicationContext。
既然是继承,那么肯定拥有BeanFactory核心功能比如一系列的getBean()功能,不同之处在于扩展了一些功能(比如加载bean定义的方式)和增加了一些功能(比如事件的支持,国际化的支持、消息的支持,应用环境的集合)。而功能的扩展肯定是反映在代码上,我们直接看代码。
首先是源头的ApplicationContext接口:
// 除了包含BeanFactory的所有功能之外,在国际化支持(MessageSource)、资源访问(如URL和文件)(ResourcePatternResolver)、事件传播(ApplicationEventPublisher)等方面进行了良好的支public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver { //环境的唯一id String getId(); //环境的名称 String getDisplayName(); //环境第一次加载的时间 long getStartupDate(); //继承自HierarchicalBeanFactory ApplicationContext getParent(); //相当于web环境实现的bean工厂 AutowireCapableBeanFactory getAutowireCapableBeanFactory() ;}
通过代码我们知道bean工厂的功能只是这个接口的一项子功能,特色的地方在于问绕bean工厂可以提供很多很使用的附加功能。
直接子类接口为ConfigurableApplicationContext,看下代码:
//是一个SPI服务提供者接口,提供配置功能的ApplicationContext,可以配置Context进行的环境、添加监听器、PostProcessor处理器、动态刷新、关闭等功能public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle { void setId(String id); //配置Context进行的环境 void setEnvironment(ConfigurableEnvironment environment); void setParent(ApplicationContext parent); //PostProcessor处理器 void addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor); //添加监听器 void addApplicationListener(ApplicationListener<?> listener); //动态刷新 void refresh() throws BeansException; void close();}
好的,这个层级关系的接口已经说完,下面看第一级抽象类AbstractApplicationContext。这个类提供了一些方法的默认实现,其中继承自BeanFactory接口方法都委托这个环境下持有的BeanFactory对象去实现,比如
public Object getBean(String name) throws BeansException { return getBeanFactory().getBean(name);}
这个类只是提供ApplicationContext中增加功能的默认实现。比如:
………………public void setId(String id) { this.id = id; } public void setEnvironment(ConfigurableEnvironment environment) { this.environment = environment; } /** * 负责存放FrameworkServlet中设置进来的监听器,当然只能是子类,因为这是抽象的。 * 当然都可以设置监听器 */ public void addApplicationListener(ApplicationListener<?> listener) { if (this.applicationEventMulticaster != null) { this.applicationEventMulticaster.addApplicationListener(listener); } else { this.applicationListeners.add(listener); } } public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); //会调用XmlWebApplicationContext.loadBeanDefinitions()方法 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() // 准备bean工厂 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasse postProcessBeanFactory(beanFactory); //对beanFactory对象本身调用在此环境中注册的processors invokeBeanFactoryPostProcessors(beanFactory); //注册所有的对bean的processors registerBeanPostProcessors(beanFactory); // Initialize message source for this context. //初始化国际化支持的bean initMessageSource(); //初始化时间发布器 initApplicationEventMulticaster(); //刷新之后执行的操作 onRefresh(); //注册事件,从bean工厂得到或者这个类设置进来的 registerListeners(); //实例化所有单例的bean finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } } ………………
其实这个类的主要的作用就是实现了refresh()方法。
下面我们俩看这个类的几个抽象方法,因为这往往是子类的价值所在:
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;protected abstract void closeBeanFactory();public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
然后看子类具体的实现——AbstractRefreshableApplicationContext
protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans();//先将所有的单例的bean destroy closeBeanFactory();//this.beanFactory = null; } try { //实例化一个工厂,这里是DefaultListableBeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); //org.springframework.web.context.WebApplicationContext:/ beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); //调用.XmlWebApplicationContext 的方法 //在本类中是抽象方法,需要子类AbstractXmlApplicationContext中实现 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } }
再次找到需要子类实现的方法loadBeanDefinitions(beanFactory);直接找到子类AbstractXmlApplicationContext中实现代码:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory){………………//这和在BeanFactory中的加载过程一样,也是委托给XmlBeanDefinitionReader去读取配置文件,XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);………………//加载bean定义loadBeanDefinitions(beanDefinitionReader);………………}
在来看loadBeanDefinitions()方法:
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) ////getConfigResources()方法的实现再次交给子类,就是读取的配置文件的源——ClassPathXmlApplicationContext Resource[] configResources = getConfigResources(); if (configResources != null) { //读取配置文件都是用的这个方法,和BeanFactory是一样的 reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); //照顾的是FileSystemXmlApplicationContext类 if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }
在来看具体子类ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,这个类比较简单,功能就是实现父类的getConfigResources()方法,就是加载读取的资源。加载的过程在构造的时候发生:
- ClassPathXmlApplicationContext中实现
public ClassPathXmlApplicationContext(String[] paths, Class clazz, ApplicationContext parent) throws BeansException { super(parent); Assert.notNull(paths, "Path array must not be null"); Assert.notNull(clazz, "Class argument must not be null"); this.configResources = new Resource[paths.length]; for (int i = 0; i < paths.length; i++) { this.configResources[i] = new ClassPathResource(paths[i], clazz); } //加载完资源文件之后就刷新工厂环境 refresh(); }
- FileSystemXmlApplicationContext中的实现
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); //简单的将路径设置到父类AbstractRefreshableConfigApplicationContext中 setConfigLocations(configLocations); if (refresh) { refresh(); } }
下面在补充ClassPathXmlApplicationContext和FileSystemXmlApplicationContext的区别:
ClassPathXmlApplicationContext[只能读放在web-info/classes目录下的配置文件],classpath:前缀是不需要的,默认就是指项目的classpath路径下面;如果要使用绝对路径,需要加上file:前缀表示这是绝对路径;
对于FileSystemXmlApplicationContext,默认表示的是两种,如果要使用classpath路径,需要前缀classpath:
1.没有盘符的是项目工作路径,即项目的根目录;
2.有盘符表示的是文件绝对路径.
- Spring IOC-ApplicationContext的继承关系
- Spring揭秘 学习笔记三 (Spring的IoC容器 ApplicationContext)
- spring IOC BeanFactory和ApplicationContext
- Spring IOC-BeanFactory的继承体系结构
- Spring 的 IOC 容器和 SpringMVC 的 IOC 容器 关系
- Spring 的 IOC 容器和 SpringMVC 的 IOC 容器 关系
- Spring IoC容器和SpringMVC IoC容器的关系
- Spring IoC——ApplicationContext示例
- IOC、Spring的IOC
- 创建spring的IOC容器时[ApplicationContext.xml] cannot be opened because it does not exist
- 【Java.Spring.Core】【IoC】ApplicationContext的附加功能(国际化,未完待续)
- Spring原理(二)IoC容器的初始化过程之ApplicationContext
- Spring IOC/BeanFactory/ApplicationContext的工作流程/实现原理/初始化/依赖注入源码详解
- Spring IOC-WebApplicationContext继承结构
- Spring揭秘(六)——Spring IoC容器ApplicationContext
- spring bean之间的关系:继承;依赖
- Spring注入有继承关系的类
- spring- bean之间的关系 继承 依赖
- 怎么像safari一样滑动的时候隐藏navigationbar?
- 思科测试命令show和debug
- VS2010+OpenCV 2.4.9环境部署
- struts2学习笔记(四)--获取Session和request方法
- 银行取款[多线程]{使用同步代码块确保线程同步}
- Spring IOC-ApplicationContext的继承关系
- 迭代器报“vector iterators incompatible”错的几种可能
- Ubuntu12.04安装vnc Server
- java 参数传递
- Android APK包名修改
- AJAX了解与用法
- CentOS下双网卡设置方法
- oracle银行卡卡号计算函数
- 性能测试监控:Linux/unix监控工具nmon