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

做网站绘制蓝图的步骤网络广告策划书案例

做网站绘制蓝图的步骤,网络广告策划书案例,php+做网站,中企动力官做网站怎么样图解 Spring 核心数据结构:BeanDefinition 其二 概述 前面写过一篇相关文章作为开篇介绍了一下BeanDefinition,本篇将深入细节来向读者展示BeanDefinition的设计,让我们一起来揭开日常开发中使用的bean的神秘面纱,深入细节透彻理解…

图解 Spring 核心数据结构:BeanDefinition 其二

概述

        前面写过一篇相关文章作为开篇介绍了一下BeanDefinition,本篇将深入细节来向读者展示BeanDefinition的设计,让我们一起来揭开日常开发中使用的bean的神秘面纱,深入细节透彻理解spring bean的概念。

一、BeanDefinition的加载过程

        首先我们来复习一下spring 容器的类的继承体系:

可以看到这是一个庞大的类继承体系,上面都是实现的接口,第一个实现类是AbstractApplicationContext,这里面有一个关键的方法fefresh(),该方法为 spring 启动入口,本文重点不是梳理这个方法,如果有需要可以留言后续出文章进行详细分析。  

 @Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.// 初始化前的准备工作,比如系统属性、环境变量的准备及验证prepareRefresh();// Tell the subclass to refresh the internal bean factory.// 初始化BeanFactory,并进行XML文件解析ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.// 准备bean和非bean// BeanFactory各种功能的填充,比如对@Qualifier和@Autowired注解的支持prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.// 扩展点,具体功能由子类实现postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.// 激活各种BeanFactory处理器invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.// 注册拦截Bean创建的后处理器,这里只是注册,真正的调用在getBean的时候registerBeanPostProcessors(beanFactory);// Initialize message source for this context.// 国际化处理// 为上下文初始化Message源,即不同语音的消息体initMessageSource();// Initialize event multicaster for this context.// 初始化应用消息广播器,并初始化"applicationEventMulticaster"beaninitApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.// 模版方法,由子类扩展onRefresh();// Check for listener beans and register them.// 在所有注册的bean中查找Listener bean,注册到消息广播器中registerListeners();// Instantiate all remaining (non-lazy-init) singletons.// 对非惰性的单例进行初始化// 一般情况下单例都会在这里就初始化了,除非指定了惰性加载finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.// 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,// 同时发出ContextRefreshedEvent时间通知别人finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}}

这里我们主要关注obtainFreshBeanFactory()方法,这个方法是初始化BeanFactory的,在初始化的过程中会解析BeanDefinition,为了继续分析BeanDefinition的解析,这时候我们需要忽略其他的一些实现逻辑,我们在AbstractRefreshableApplicationContext中找到一个抽象方法:

	/*** 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*/protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)throws BeansException, IOException;

看注释就知道这个方法是加载BeanDefinition的,我们找到了方法实现类:AnnotationConfigWebApplicationContext和XmlBeanDefinitionReader,可以明显的看出来这两个实现类一个是解析注解方式的,一个是xml配置方式的,限于篇幅这里分析一下经典的xml方式。

        如下是XmlBeanDefinitionReader中的实现:

	/*** Loads the bean definitions via an XmlBeanDefinitionReader.* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader* @see #initBeanDefinitionReader* @see #loadBeanDefinitions*/@Overrideprotected 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(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);}

这里首先定义了一个xml文件读取类XmlBeanDefinitionReader,,之后继续跟进源码:

/*** Load the bean definitions with the given XmlBeanDefinitionReader.* <p>The lifecycle of the bean factory is handled by the refreshBeanFactory method;* therefore this method is just supposed to load and/or register bean definitions.* <p>Delegates to a ResourcePatternResolver for resolving location patterns* into Resource instances.* @throws IOException if the required XML document isn't found* @see #refreshBeanFactory* @see #getConfigLocations* @see #getResources* @see #getResourcePatternResolver*/protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {String[] configLocations = getConfigLocations();if (configLocations != null) {for (String configLocation : configLocations) {reader.loadBeanDefinitions(configLocation);}}}

可以看到这里是循环遍历从配置的目录中加载BeanDefinition,继续跟进loadBeanDefinitions()方法

,我们找到了实际加载BeanDefinition的方法:

/*** Actually load bean definitions from the specified XML file.* @param inputSource the SAX InputSource to read from* @param resource the resource descriptor for the XML file* @return the number of bean definitions found* @throws BeanDefinitionStoreException in case of loading or parsing errors* @see #doLoadDocument* @see #registerBeanDefinitions*/protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {try {Document doc = doLoadDocument(inputSource, resource);int count = registerBeanDefinitions(doc, resource);if (logger.isDebugEnabled()) {logger.debug("Loaded " + count + " bean definitions from " + resource);}return count;}catch (BeanDefinitionStoreException ex) {throw ex;}catch (SAXParseException ex) {throw new XmlBeanDefinitionStoreException(resource.getDescription(),"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);}catch (SAXException ex) {throw new XmlBeanDefinitionStoreException(resource.getDescription(),"XML document from " + resource + " is invalid", ex);}catch (ParserConfigurationException ex) {throw new BeanDefinitionStoreException(resource.getDescription(),"Parser configuration exception parsing XML from " + resource, ex);}catch (IOException ex) {throw new BeanDefinitionStoreException(resource.getDescription(),"IOException parsing XML document from " + resource, ex);}catch (Throwable ex) {throw new BeanDefinitionStoreException(resource.getDescription(),"Unexpected exception parsing XML document from " + resource, ex);}}

继续往下跟进我们到了Bean注册的方法中:

/*** Register each bean definition within the given root {@code <beans/>} element.*/@SuppressWarnings("deprecation")  // for Environment.acceptsProfiles(String...)protected void doRegisterBeanDefinitions(Element root) {// Any nested <beans> elements will cause recursion in this method. In// order to propagate and preserve <beans> default-* attributes correctly,// keep track of the current (parent) delegate, which may be null. Create// the new (child) delegate with a reference to the parent for fallback purposes,// then ultimately reset this.delegate back to its original (parent) reference.// this behavior emulates a stack of delegates without actually necessitating one.BeanDefinitionParserDelegate parent = this.delegate;BeanDefinitionParserDelegate current = createDelegate(getReaderContext(), root, parent);this.delegate = current;if (current.isDefaultNamespace(root)) {String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);if (StringUtils.hasText(profileSpec)) {String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);// We cannot use Profiles.of(...) since profile expressions are not supported// in XML config. See SPR-12458 for details.if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {if (logger.isDebugEnabled()) {logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +"] not matching: " + getReaderContext().getResource());}return;}}}preProcessXml(root);parseBeanDefinitions(root, current);postProcessXml(root);this.delegate = parent;}

这里我们关注一下这个方法:

	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {importBeanDefinitionResource(ele);}else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {processAliasRegistration(ele);}else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {processBeanDefinition(ele, delegate);}else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {// recursedoRegisterBeanDefinitions(ele);}}

这里就是根据xml中配置的标签元素来进行处理的,我们可以打开BeanDefinitionParserDelegate

类,发现我们找到了xml中标签元素的定义了。

        到这里主流程基本讲完了细节不再拖沓了,直接进入DefaultListableBeanFactory类中,到此我们发现这样一行代码:

this.beanDefinitionMap.put(beanName, beanDefinition);

原来我们的bean最终都是存放在map中的:

/** Map of bean definition objects, keyed by bean name. */private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

二、BeanDefinition的详细分析

        经过上一节漫长的更近源码分析,我们终于知道了平时使用的bean的加载和存储细节了,到这里我们需要进一步追问spirng BeanDefinition 存放了哪些信息呢?这样才算是真正的理解了bean。

Spring的BeanDefinition用于描述Spring Bean的元数据信息,它包含了以下主要信息:

  1. Bean的类名:定义了Bean的实际类是什么。

  2. Bean的作用域:例如singletonprototyperequestsession等。

  3. Bean的依赖关系:其他Bean作为构造函数或者设置方法的参数。

  4. Bean的lazy初始化标志:表示Bean是否在容器启动时就被实例化。

  5. Bean的自动装配模式:如按类型自动装配、按名称自动装配。

  6. Bean的工厂方法:如果Bean是通过FactoryBean创建的,这里会记录工厂方法的名称。

  7. Bean的属性:包括构造函数参数、属性值等。

  8. Bean的初始化方法和销毁方法:指定Bean的初始化和销毁时调用的方法。

这些信息在Spring容器的Bean定义阶段被解析和存储的,用于之后Bean的实例化和依赖注入等阶段。

总结

        花费了两个小时总算是把Spring 核心数据结构:BeanDefinition讲解清晰了,写文章既需要对所写文章技术点有深入的了解还需要耐心。这些内容也都不是什么新的事物了,但是每个人还是需要自己去跟进一遍源码并结合自身的知识去分析消化一下才能更深入的理解到,希望文章能够给读者有一定的帮助。


文章转载自:
http://dinncofilmily.tpps.cn
http://dinncoprotonotary.tpps.cn
http://dinncoawedness.tpps.cn
http://dinncosellout.tpps.cn
http://dinncoenumerative.tpps.cn
http://dinncoacerbity.tpps.cn
http://dinncofrigidarium.tpps.cn
http://dinncodwarf.tpps.cn
http://dinncoflawless.tpps.cn
http://dinncobanteringly.tpps.cn
http://dinncoexeunt.tpps.cn
http://dinncowhereinto.tpps.cn
http://dinncolowlihead.tpps.cn
http://dinncoultrarightist.tpps.cn
http://dinncotextolite.tpps.cn
http://dinncocaracal.tpps.cn
http://dinncoseasonably.tpps.cn
http://dinncounequipped.tpps.cn
http://dinncoamongst.tpps.cn
http://dinncodiamondback.tpps.cn
http://dinncoconciliation.tpps.cn
http://dinncovga.tpps.cn
http://dinncocontrollable.tpps.cn
http://dinncosarcomata.tpps.cn
http://dinncokaf.tpps.cn
http://dinncomoralization.tpps.cn
http://dinncoannouncement.tpps.cn
http://dinncoglaringness.tpps.cn
http://dinncomisregister.tpps.cn
http://dinncoparorexia.tpps.cn
http://dinncogenerator.tpps.cn
http://dinncorote.tpps.cn
http://dinncosixscore.tpps.cn
http://dinncotsarism.tpps.cn
http://dinncoamoral.tpps.cn
http://dinncogunman.tpps.cn
http://dinncounlink.tpps.cn
http://dinncosubjection.tpps.cn
http://dinncocordiform.tpps.cn
http://dinncoresite.tpps.cn
http://dinncogneiss.tpps.cn
http://dinncobibitory.tpps.cn
http://dinncoexploringly.tpps.cn
http://dinncochintzy.tpps.cn
http://dinncospendthrift.tpps.cn
http://dinncotoenail.tpps.cn
http://dinncovictim.tpps.cn
http://dinncowheeziness.tpps.cn
http://dinncocitrange.tpps.cn
http://dinncoprebiologic.tpps.cn
http://dinncoobstupefy.tpps.cn
http://dinncowrap.tpps.cn
http://dinncobaywreath.tpps.cn
http://dinncoimmunoregulation.tpps.cn
http://dinncodoukhobors.tpps.cn
http://dinncowilno.tpps.cn
http://dinncoalbescent.tpps.cn
http://dinncometasomatic.tpps.cn
http://dinncocalycoid.tpps.cn
http://dinncobivalence.tpps.cn
http://dinncophantasmal.tpps.cn
http://dinncofalasha.tpps.cn
http://dinncotriandrous.tpps.cn
http://dinncorupicoline.tpps.cn
http://dinncoromany.tpps.cn
http://dinncoddn.tpps.cn
http://dinncoscrupulously.tpps.cn
http://dinncogunfignt.tpps.cn
http://dinncotubercula.tpps.cn
http://dinncoflyunder.tpps.cn
http://dinncofelsitic.tpps.cn
http://dinncohomebody.tpps.cn
http://dinncoscallop.tpps.cn
http://dinncodialectic.tpps.cn
http://dinncorubbingstone.tpps.cn
http://dinncospongeous.tpps.cn
http://dinncoinstance.tpps.cn
http://dinncoquartic.tpps.cn
http://dinncoextinguish.tpps.cn
http://dinncorosinweed.tpps.cn
http://dinncobanquo.tpps.cn
http://dinncomateriality.tpps.cn
http://dinncorudeness.tpps.cn
http://dinncoeuphemise.tpps.cn
http://dinncodriveline.tpps.cn
http://dinncomarshall.tpps.cn
http://dinncoaccepter.tpps.cn
http://dinncorectum.tpps.cn
http://dinncospeel.tpps.cn
http://dinncolaboring.tpps.cn
http://dinncotelestereoscope.tpps.cn
http://dinncosunroom.tpps.cn
http://dinncoaril.tpps.cn
http://dinncoconspicuous.tpps.cn
http://dinncoperambulate.tpps.cn
http://dinncoignitability.tpps.cn
http://dinncophanerophyte.tpps.cn
http://dinncohakeem.tpps.cn
http://dinncoextended.tpps.cn
http://dinncobasseterre.tpps.cn
http://www.dinnco.com/news/124779.html

相关文章:

  • 建筑工人招聘平台seo关键词优化举例
  • 政府网站源码下载软文代发平台
  • 怎么查找网站的根目录免费的拓客平台有哪些
  • 网站空间不续费seo的优缺点
  • 网络优化中是什么意思西安网站优化公司
  • 有专门做宝宝用品的网站吗能打开各种网站的浏览器下载
  • 高端大气网站案例怎么做私人网站
  • win2003 iis配置网站下载百度推广app
  • 门户网站的建设费用广告软文范例
  • 河池市城乡住房建设厅网站小网站
  • 网站优化模板网络营销案例分析论文
  • 广东省会计信息服务平台百度seo优
  • 手机做炫光头像图的网站企业网站怎么做
  • 电脑系统做的好的几个网站经典seo伪原创
  • 网站建设高端热门搜索关键词
  • 网站开发背景怎么写百度词条官网入口
  • 网站开发与设计多少钱一个网站自媒体平台注册入口官网
  • 做网站第二年要续费吗seo课培训
  • 关键词推广技巧上海seo搜索优化
  • 查网站开发语言googlechrome浏览器
  • 网站推广计划包含的主要内容百度网站推广费用
  • 网站可以制作iosaso优化{ }贴吧
  • 武汉今天特大新闻网站优化检测工具
  • 创意设计之都seo自学
  • 做网站多久能盈利武汉网站seo推广
  • 定做网站多少钱荥阳网络推广公司
  • 网站后台改成只有一个管理员登陆软件推广的渠道是哪里找的
  • 整合营销网站网络广告策划书案例
  • 南宁网站建设公司怎么接单磁力宅
  • 学校官网主页网页设计企业seo职位