当前位置: 首页 > news >正文

今日兰州疫情最新消息/谷歌seo博客

今日兰州疫情最新消息,谷歌seo博客,小程序开发一个多少钱,杭州网站建设费用多少钱以编程的方式使用DefaultListableBeanFactory时,首先定义一个Resource来定位容器使用的BeanDefinition。这是使用的是ClassPathResource,意味着Spring会在类路径中去寻找以文件形式存在的BeanDefinition的信息。 ClassPathResource res new ClassPathRes…

以编程的方式使用DefaultListableBeanFactory时,首先定义一个Resource来定位容器使用的BeanDefinition。这是使用的是ClassPathResource,意味着Spring会在类路径中去寻找以文件形式存在的BeanDefinition的信息。

ClassPathResource res =new ClassPathResource('beans.xml');

这里定义的Resource不能由DefaultListableBeanFactory直接使用,Spring通过BeanDefinitionReader来对这些信息进行处理。在这里,我们也可以看到使用ApplicationContext相对于直接使用DefaultListableBeanFactory的好处。在ApplicationContext中,提供了一系列加载不同Resource的读取器的实现,而DefaultListableBeanFactory只是一个纯粹的IOC容器,需要为它配置特定的读取器来完成功能。但是使用DefaultListableBeanFactory这种底层的容器,能提高IOC容器的灵活性。

我们经常使用的ApplicationContext,比如FileSystemXmlApplicationContext、ClassPathXmlSystemXmlApplicationContext以及XmlWebApplicationContext。从类的名字可以看出它们提供哪些不同的Resource读入功能,依次比如为从文件系统,从class path,从web容器载入Resource等。

 

我们以FileSystemXmlApplicationContext为例,继承关系如下图:

因为基类是DefaultResourceLoader(它实现了ResourceLoader接口),这个FileSystemXmlApplicationContext已经具备ResourceLoader的读入功能。

先看下FileSystemXmlApplicationContext的实现:

public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {/*** Create a new FileSystemXmlApplicationContext for bean-style configuration.* @see #setConfigLocation* @see #setConfigLocations* @see #afterPropertiesSet()*/public FileSystemXmlApplicationContext() {}/*** Create a new FileSystemXmlApplicationContext for bean-style configuration.* @param parent the parent context* @see #setConfigLocation* @see #setConfigLocations* @see #afterPropertiesSet()*/public FileSystemXmlApplicationContext(ApplicationContext parent) {super(parent);}/*** Create a new FileSystemXmlApplicationContext, loading the definitions* from the given XML file and automatically refreshing the context.* @param configLocation file path* @throws BeansException if context creation failed*///这个构造函数的configLocation包含的是BeanDefinition所在的文件路径public FileSystemXmlApplicationContext(String configLocation) throws BeansException {this(new String[] {configLocation}, true, null);}/*** Create a new FileSystemXmlApplicationContext, loading the definitions* from the given XML files and automatically refreshing the context.* @param configLocations array of file paths* @throws BeansException if context creation failed*///这个构造函数的configLocation包含多个BeanDefinition的文件路径public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {this(configLocations, true, null);}/*** Create a new FileSystemXmlApplicationContext with the given parent,* loading the definitions from the given XML files and automatically* refreshing the context.* @param configLocations array of file paths* @param parent the parent context* @throws BeansException if context creation failed*///这个构造函数的configLocation包含的多个BeanDefinition文件路径的同时,还允许指定自己的双亲IOC容器public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {this(configLocations, true, parent);}/*** Create a new FileSystemXmlApplicationContext, loading the definitions* from the given XML files.* @param configLocations array of file paths* @param refresh whether to automatically refresh the context,* loading all bean definitions and creating all singletons.* Alternatively, call refresh manually after further configuring the context.* @throws BeansException if context creation failed* @see #refresh()*/public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {this(configLocations, refresh, null);}/*** Create a new FileSystemXmlApplicationContext with the given parent,* loading the definitions from the given XML files.* @param configLocations array of file paths* @param refresh whether to automatically refresh the context,* loading all bean definitions and creating all singletons.* Alternatively, call refresh manually after further configuring the context.* @param parent the parent context* @throws BeansException if context creation failed* @see #refresh()*///在对象的初始化过程中,调用refresh方法载入BeanDefinition,这个refresh方法启动了BeanDefinition的载入过程,待会看refresh详细分析public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)throws BeansException {super(parent);setConfigLocations(configLocations);if (refresh) {refresh();}}/*** Resolve resource paths as file system paths.* <p>Note: Even if a given path starts with a slash, it will get* interpreted as relative to the current VM working directory.* This is consistent with the semantics in a Servlet container.* @param path path to the resource* @return Resource handle* @see org.springframework.web.context.support.XmlWebApplicationContext#getResourceByPath*/@Override//这是应用于文件系统中的Resource的实现,通过构造一个FileSystemResource来得到一个文件在//系统中定位的BeanDefinition//这个getResourceByPath是在BeanDefinitionReader的loadBeanDefinition中被调用//loadBeanDefinition采用模板模式,具体的定位实现是由各个子类来完成protected Resource getResourceByPath(String path) {if (path != null && path.startsWith("/")) {path = path.substring(1);}return new FileSystemResource(path);}}

refresh方法非常重要,容器初始化过程的一个重要入口。refresh()在AbstractApplicationContext实现,看下部分代码:

    public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.
            prepareRefresh();// Tell the subclass to refresh the internal bean factory.//子类中启动refreshBeanFactory的地方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.//设置beanFactory的后置处理
                postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.//调用beanFactory的后置处理器,这些后处理器在bean中向容器注册的
                invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.//注册bean的后处理器,在bean创建过程中调用
                registerBeanPostProcessors(beanFactory);// Initialize message source for this context.//对上下文中的消息源进行初始化
                initMessageSource();// Initialize event multicaster for this context.//初始化上下文中的事件机制
                initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.//初始化其中的特殊bean
                onRefresh();// Check for listener beans and register them.//检查监听bean并且将这些bean向容器注册
                registerListeners();// Instantiate all remaining (non-lazy-init) singletons.//实例化所有non-lazy-init单件
                finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.//发布容器事件,结束refresh过程
                finishRefresh();}catch (BeansException ex) {// Destroy already created singletons to avoid dangling resources.//为防止bean资源占用,在异常处理中,销毁已经在前面过程中生成的单件bean
                destroyBeans();// Reset 'active' flag.//重置active标志
                cancelRefresh(ex);// Propagate exception to caller.throw ex;}}}
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (logger.isDebugEnabled()) {logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }

 


在IOC容器的初始化过程中,BeanDefinition的定位,读入和载入过程是分开进行的,这是解耦的一个体现。关于读入器的配置,要先看下FileSystemXmlApplicationContext的基类AbstractRefreshableApplicationContext实现。需要重点看你下AbstractRefreshableApplicationContext的refreshBeanFactory方法,这个refreshBeanFactory被FileSystemXmlApplicationContext构造函数中的refresh方法调用(refresh方法调用了obtainFreshBeanFactory()上面代码可以看出)。

下面看下AbstractRefreshableApplicationContext对容器初始化的代码清单

protected final void refreshBeanFactory() throws BeansException {if (hasBeanFactory()) {destroyBeans();closeBeanFactory();}try {//创建ioc容器,DefaultListableBeanFactoryDefaultListableBeanFactory beanFactory = createBeanFactory();beanFactory.setSerializationId(getId());customizeBeanFactory(beanFactory);//启动对BeanDefinition的载入
            loadBeanDefinitions(beanFactory);synchronized (this.beanFactoryMonitor) {this.beanFactory = beanFactory;}}catch (IOException ex) {throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);}}

在这个方法中,通过createBeanFactory方法构建了一个IOC容器供Application使用。这个IOC容器就是前面提到的DefaultListableBeanFactory,同时它启动了loadBeanDefinitions来载入BeanDefinition。

//这就是在上下文中创建DefaultListableBeanFactory的地方,getInternalParentBeanFactory()的具体实现在//AbstractApplicationContext,会根据已有的双亲IOC容器信息来完成DefaultListableBeanFactory的双亲IOC容器protected DefaultListableBeanFactory createBeanFactory() {return new DefaultListableBeanFactory(getInternalParentBeanFactory());}/*** *     protected BeanFactory getInternalParentBeanFactory() {return (getParent() instanceof ConfigurableApplicationContext) ?((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent();}*/
/*** Load bean definitions into the given bean factory, typically through* delegating to one or more bean definition readers.* @param beanFactory the bean factory to load bean definitions into* @throws BeansException if parsing of the bean definitions failed* @throws IOException if loading of bean definition files failed* @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader*///这里是使用 BeanDefinitionReader载入Bean定义的地方,因为允许有多种载入方式,虽然用的最多的是XML定义的形式,//这里通过一个抽象函数把具体的实现委托给子类完成protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)throws BeansException, IOException;

 

    public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {//取得ResourceLoader使用的是DefaultResourceLoaderResourceLoader resourceLoader = getResourceLoader();if (resourceLoader == null) {throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");}//对Resource路径解析,Resource集合可以是多个文件if (resourceLoader instanceof ResourcePatternResolver) {// Resource pattern matching available.try {//取得具体的Resource定位Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);int loadCount = loadBeanDefinitions(resources);if (actualResources != null) {for (Resource resource : resources) {actualResources.add(resource);}}if (logger.isDebugEnabled()) {logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");}return loadCount;}catch (IOException ex) {throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", ex);}}else {// Can only load single resources by absolute URL.Resource resource = resourceLoader.getResource(location);int loadCount = loadBeanDefinitions(resource);if (actualResources != null) {actualResources.add(resource);}if (logger.isDebugEnabled()) {logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");}return loadCount;}}


对于取得Resource的过程,看下DefaultResourceLoader是怎么完成的

 

public Resource getResource(String location) {Assert.notNull(location, "Location must not be null");if (location.startsWith(CLASSPATH_URL_PREFIX)) { //     public static final String CLASSPATH_URL_PREFIX = "classpath:";return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());}else {try {// Try to parse the location as a URL...//这里处理URL标识的Resource定位URL url = new URL(location);return new UrlResource(url);}catch (MalformedURLException ex) {// No URL -> resolve as resource path.//如果既不是classpath,也不是URL标识的Resource定位,则把getResource交给getResourceByPath,//这个方法是一个protected方法,默认实现是得到一个ClassPathContextResource,这个方法会用子类实现return getResourceByPath(location);}}}
    protected Resource getResourceByPath(String path) {return new ClassPathContextResource(path, getClassLoader());}

对于上面的FileSystemXmlApplicationContext对getResourceByPath方法的实现就是下面方法

    @Override//这是应用于文件系统中的Resource的实现,通过构造一个FileSystemResource来得到一个文件在//系统中定位的BeanDefinition//这个getResourceByPath是在BeanDefinitionReader的loadBeanDefinition中被调用//loadBeanDefinition采用模板模式,具体的定位实现是由各个子类来完成protected Resource getResourceByPath(String path) {if (path != null && path.startsWith("/")) {path = path.substring(1);}return new FileSystemResource(path);}


返回的FileSystemResource对象,Spring可以进行相关的I/O操作,完成BeanDefinition的定位。

如果是其他的ApplicationContext,那么会对应生成其他种类的Resource。比如ClassPathResource、ServletContextResource等。关于Resource种类,可以看下继承关系图

作为接口的Resource定义了许多与I/O相关的操作。

通过前面的实现原理的分析,我们以FileSystemXmlApplicationContext的实现原理为例,了解了Resource的定位问题,既是FileSystem方式存在的Resource的定位实现。在在BeanDefinition定位完成的基础上,就可以通过返回的Resource对象来进行载入了。在定位过程完成以后,为BeanDefinition的载入创造了I/O操作的条件,但是具体的数据还没有开始读入。

 

转载于:https://www.cnblogs.com/xiaoblog/p/4269873.html

http://www.lbrq.cn/news/1467937.html

相关文章:

  • 男人和女人做性网站/爱站网seo工具
  • dede网站迁移步骤/平台推广员是做什么的
  • 武汉网站建设优化/网站推广方案有哪些
  • 企业3合1网站建设/网站推广seo方法
  • 怎么做网站把图片发到网上/网站建设服务公司
  • 深圳做网站价格/网站你应该明白我的意思吗
  • 做网站策划案/百度快速排名优化技术
  • 阿里云备案网站建设方案书案例/营销型公司网站建设
  • 北京网站设计公司新鸿儒/近期国内外重大新闻10条
  • 国内net开发的网站建设/网络营销的产品策略
  • 织梦可以做大型网站吗/百度seo优化是什么
  • 企业网查询四六级/深圳seo优化电话
  • 开源房产网站源码/设计公司网站设计
  • 运营网站团队建设/app营销十大成功案例
  • 企业网站建设注意/营销策略ppt
  • 梅林网站建设/保定网站seo
  • 自己做网站想更换网址/整合营销沟通
  • 阿里企业邮箱客服人工电话/使用 ahrefs 进行 seo 分析
  • 现在哪些做进口商品的电商网站/如何做百度免费推广
  • 网上商城建设方案/哈尔滨优化网站方法
  • 电商网站的支付接入该怎么做呢/seo建站还有市场吗
  • 微商怎么做自己的网站/seo排名工具提升流量
  • 投稿网站源码/推广形式
  • 网站获取访问者qq号码/网站建设报价方案
  • 网站的客服一般怎么做的/网络优化工程师证书
  • 邯郸公司网站建设/淘数据官网
  • 帮忙注册公司要多少钱/seo学校
  • 网站开发到上线需要多久/seo好学吗入门怎么学
  • 网站服务器如何做热备价/云搜索系统
  • 佛山外贸网站建设/键词优化排名
  • 图像加密学习日志————论文学习DAY4
  • sqli-labs:65个关卡的文章汇总
  • Java高性能编程实践指南
  • 【Android】RecyclerView实现新闻列表布局(1)适配器使用相关问题
  • 鸿蒙智选携手IAM进驻长隆熊猫村,为国宝打造智慧健康呼吸新空间
  • 使用 whisper, 音频分割, 整理需求 2