国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring IOC源碼跟蹤記錄-基于XML

Big_fat_cat / 1727人閱讀

摘要:在有了之后,類與類之間的耦合關(guān)系是這樣的。為刷新做好準(zhǔn)備。初始化上下文消息為這個(gè)上下文初始化事件多播器。

what is IOC?

IOC(Inversion of Control )控制反轉(zhuǎn),是Spring框架最重要的一個(gè)特性,提供了一個(gè)裝載類的容器來為類之間進(jìn)行解耦,并提供了一系列的擴(kuò)展接口,使得開發(fā)者可以在bean的生命周期里自定義一些行為操作。

在沒有IOC之前,類與類之間的耦合關(guān)系是這樣的。這兒僅僅只有5個(gè)類,類之間的耦合關(guān)系就如此復(fù)雜,難以想象當(dāng)類的數(shù)量隨著業(yè)務(wù)發(fā)展而爆炸增多的時(shí)候,耦合關(guān)系是多么的糟糕。

在有了IOC之后,類與類之間的耦合關(guān)系是這樣的。所有類都注冊在IOC容器上,所有類只和IOC容器耦合,并且IOC容器為所有管理的類提供生命周期的管理。

how IOC do?

可以看出來IOC容器很像我們生活中的百貨商場,我們需要什么東西都可以去百貨商場買到,在沒有百貨商場以前我們買菜需要去菜市場,買手機(jī)需要去手機(jī)店,買電腦需要到電腦城......極大的方便了獲取類的方式。接下來我通過Debug源碼的方式來追一追整個(gè)IOC啟動過程的步驟,希望能揭開這個(gè)“百貨商場”的神秘面紗。

這是我們debug的入口,用的是最基礎(chǔ)的XML解析的方式。

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
HelloService service = (HelloService) context.getBean("service");
service.say();
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
      throws BeansException {
   super(parent); //設(shè)置parent父容器
   setConfigLocations(configLocations);//讓ioc容器感知到xml配置文件
   if (refresh) {
      refresh();
   }
}

做的第一步是super(parent),可以看出IOC容器是具備父子關(guān)系的,順便提一下,這個(gè)特性在SpringMVC中體現(xiàn)出來了,SpringMVC的容器是 Spring容器的子容器,這樣的結(jié)果就是Controller(SpringMVC容器中的Bean)可以調(diào)用Service(Spring容器中的類),而反過來則不行,這樣一定程度保證了類之間的單向關(guān)系,以及調(diào)用方式不可逆,使得容器更加安全。

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // 為刷新做好準(zhǔn)備。
      prepareRefresh();
      // 告訴子類刷新內(nèi)部bean工廠。
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      // 準(zhǔn)備beanfactory,為使用ioc容器做好準(zhǔn)備
      prepareBeanFactory(beanFactory);
      try {
         // 允許beanfactory準(zhǔn)備好后做一些事情,擴(kuò)展點(diǎn)
         postProcessBeanFactory(beanFactory);
         // 將bean注冊在ioc容器
         invokeBeanFactoryPostProcessors(beanFactory);
         // 注冊攔截bean創(chuàng)建的bean處理器。
         registerBeanPostProcessors(beanFactory);
         // 初始化上下文消息
         initMessageSource();
         // 為這個(gè)上下文初始化事件多播器。
         initApplicationEventMulticaster();
         // 初始化特定上下文子類中的其他特殊bean。
         onRefresh();
         // 檢查listener類并注冊它們
         registerListeners();
         // 實(shí)例化所有的lazy-init單例
         finishBeanFactoryInitialization(beanFactory);
         // 最后一步:發(fā)布相應(yīng)的事件
         finishRefresh();
      }
      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }
         // 銷毀已經(jīng)創(chuàng)建的單例
         destroyBeans();
         // 重置active的值
         cancelRefresh(ex);
         // 將異常傳播給調(diào)用者
         throw ex;
      }
      finally {
         //清空一些元數(shù)據(jù)的內(nèi)存,這些元數(shù)據(jù)生成了單例模式后就再也用不到了
         resetCommonCaches();
      }
   }
}

這里是ioc容器的誕生點(diǎn) createBeanFactory()

protected final void refreshBeanFactory() throws BeansException {
......

      DefaultListableBeanFactory beanFactory = createBeanFactory();
......
      loadBeanDefinitions(beanFactory);
......
}

再看看loadBeanDefinitions()方法 ,這里解釋下什么是BeanDefinition (所有的Bean在Spring容器中的數(shù)據(jù)結(jié)構(gòu)都是BeanDefinition,其中包含了跟這個(gè)bean相關(guān)的所有信息)beanDefinitionReader可以看做是一個(gè)IOC容器bean的生產(chǎn)者,可以從外部環(huán)境(xml,注解等)獲取到bean的信息并裝載進(jìn)去,這個(gè)方法對beanDefinitionReader 設(shè)置了ResourceLoader,EnitityResolver等等對解析xml文件很重要的類,繼續(xù)Debug看。

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);
}

ResourceLoader會去解析xml文件,將每個(gè)xml中的每個(gè)元素都解析然后返回一個(gè)DOM的文檔樹便于后續(xù)操作。

接著會執(zhí)行prepareBeanFactory方法,這個(gè)方法類似一個(gè)制定ioc規(guī)則的方法,讓哪些接口的bean不注冊進(jìn)去,哪些接口的bean注冊進(jìn)去

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // Tell the internal bean factory to use the context"s class loader etc.
   beanFactory.setBeanClassLoader(getClassLoader());
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

   // Configure the bean factory with context callbacks.
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

   // BeanFactory interface not registered as resolvable type in a plain factory.
   // MessageSource registered (and found for autowiring) as a bean.
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);

   // Register early post-processor for detecting inner beans as ApplicationListeners.
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

   // Detect a LoadTimeWeaver and prepare for weaving, if found.
   if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      // Set a temporary ClassLoader for type matching.
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }

   // Register default environment beans.
   if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
   }
}

之后會對實(shí)現(xiàn)了BeanFactoryPostProcessor接口的類處理,該擴(kuò)展點(diǎn)允許在(容器已經(jīng)初始完成,但是bean還沒有初始化這部分時(shí)間進(jìn)行擴(kuò)展),體現(xiàn)了Spring的擴(kuò)展性。

又看到了一個(gè)擴(kuò)展點(diǎn),BeanPostProcessor,該擴(kuò)展點(diǎn)允許在bean 初始化之前或者之后的時(shí)候進(jìn)行擴(kuò)展

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

接下來回去預(yù)實(shí)例化沒有設(shè)置lazy-init的類

beanFactory.preInstantiateSingletons();    

進(jìn)入這個(gè)方法體,在debug已經(jīng)可以看到自己設(shè)置的bean的id值了

可以看到除了類之外還有scope,lazyInit,primary等屬性

這兒走了一遍getBean的邏輯,不過因?yàn)闆]有初始化,去到的實(shí)例都是null,接著會標(biāo)記即將創(chuàng)建的bean,并將其緩存

/**
 標(biāo)記已創(chuàng)建的(或即將創(chuàng)建的)指定bean。
這允許bean工廠優(yōu)化其緩存重復(fù)。
創(chuàng)建指定的bean。
 * @param beanName the name of the bean
 */
protected void markBeanAsCreated(String beanName) {
   if (!this.alreadyCreated.contains(beanName)) {
      synchronized (this.mergedBeanDefinitions) {
         if (!this.alreadyCreated.contains(beanName)) {
            // Let the bean definition get re-merged now that we"re actually creating
            // the bean... just in case some of its metadata changed in the meantime.
            clearMergedBeanDefinition(beanName);
            this.alreadyCreated.add(beanName);
         }
      }
   }
}

馬上進(jìn)入實(shí)例化bean的代碼,其中createBean()是重點(diǎn)

// Create bean instance.
if (mbd.isSingleton()) {
   sharedInstance = getSingleton(beanName, new ObjectFactory() {
      @Override
      public Object getObject() throws BeansException {
         try {
            return createBean(beanName, mbd, args);  
         }
         catch (BeansException ex) {
            // Explicitly remove instance from singleton cache: It might have been put there
            // eagerly by the creation process, to allow for circular reference resolution.
            // Also remove any beans that received a temporary reference to the bean.
            destroySingleton(beanName);
            throw ex;
         }
      }
   });

追了好幾層終于看到,bean是通過反射實(shí)例化的。

Class resolvedClass = ClassUtils.forName(className, classLoader);

如果是singleton,直接從map里面取,如果沒有則通過反射生成,放進(jìn)map中然后返回,如果是prototype則每次獲取都會實(shí)例化,返回一個(gè)新的。

if (mbd.isSingleton()) {
   sharedInstance = getSingleton(beanName, new ObjectFactory() {
      @Override
      public Object getObject() throws BeansException {
         try {
            return createBean(beanName, mbd, args);
         }
         catch (BeansException ex) {
            // Explicitly remove instance from singleton cache: It might have been put there
            // eagerly by the creation process, to allow for circular reference resolution.
            // Also remove any beans that received a temporary reference to the bean.
            destroySingleton(beanName);
            throw ex;
         }
      }
   });
   bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) {
   // It"s a prototype -> create a new instance.
   Object prototypeInstance = null;
   try {
      beforePrototypeCreation(beanName);
      prototypeInstance = createBean(beanName, mbd, args);
   }
   finally {
      afterPrototypeCreation(beanName);
   }
   bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

這就是緩存單例bean的map

private final Map singletonObjects = new ConcurrentHashMap(256);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   Object singletonObject = this.singletonObjects.get(beanName);
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
         singletonObject = this.earlySingletonObjects.get(beanName);
         if (singletonObject == null && allowEarlyReference) {
            ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
               singletonObject = singletonFactory.getObject();
               this.earlySingletonObjects.put(beanName, singletonObject);
               this.singletonFactories.remove(beanName);
            }
         }
      }
   }
   return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
總結(jié)

ResourceLoader對xml文檔樹進(jìn)行讀取解析生成Resource文件,Resource文件封裝了對xml文件的IO操作,然后BeanDefinitionReader會對Resource文件讀取并生成BeanDefinition放在BeanDefinitionRegistry里面,過后beanFactoryPostProcesser會解析占位符,然后SimpleInstantiationStrategy會通過反射實(shí)例化,然后BeanWrapper會對非lazy-init的bean進(jìn)行賦值,在getBean的時(shí)候IOC容器通過Map緩存的方式來達(dá)到單例的效果。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/76673.html

相關(guān)文章

  • Spring AOP從零單排-織入時(shí)期源碼分析

    摘要:何為簡單點(diǎn)來定義就是切面,是一種編程范式。定義一個(gè)切面的載體定義一個(gè)切點(diǎn)定義一個(gè)為,并指定對應(yīng)的切點(diǎn)一個(gè)注冊配置類,啟動容器,初始化時(shí)期獲取對象,獲取對象時(shí)期,并進(jìn)行打印好了,這樣我們整體的代理就已經(jīng)完成。 問題:Spring AOP代理中的運(yùn)行時(shí)期,是在初始化時(shí)期織入還是獲取對象時(shí)期織入? 織入就是代理的過程,指目標(biāo)對象進(jìn)行封裝轉(zhuǎn)換成代理,實(shí)現(xiàn)了代理,就可以運(yùn)用各種代理的場景模式。 ...

    honmaple 評論0 收藏0
  • 仿照 Spring 實(shí)現(xiàn)簡單的 IOC 和 AOP - 下篇

    摘要:在上文中,我實(shí)現(xiàn)了一個(gè)很簡單的和容器。比如,我們所熟悉的就是在這里將切面邏輯織入相關(guān)中的。初始化的工作算是結(jié)束了,此時(shí)處于就緒狀態(tài),等待外部程序的調(diào)用。其中動態(tài)代理只能代理實(shí)現(xiàn)了接口的對象,而動態(tài)代理則無此限制。 1. 背景 本文承接上文,來繼續(xù)說說 IOC 和 AOP 的仿寫。在上文中,我實(shí)現(xiàn)了一個(gè)很簡單的 IOC 和 AOP 容器。上文實(shí)現(xiàn)的 IOC 和 AOP 功能很單一,且 I...

    AlexTuan 評論0 收藏0
  • Spring專題之IOC源碼分析

    摘要:前言以下源碼基于版本解析。實(shí)現(xiàn)源碼分析對于的實(shí)現(xiàn),總結(jié)來說就是定位加載和注冊。定位就是需要定位配置文件的位置,加載就是將配置文件加載進(jìn)內(nèi)存注冊就是通過解析配置文件注冊。下面我們從其中的一種使用的方式一步一步的分析的實(shí)現(xiàn)源碼。 前言 以下源碼基于Spring 5.0.2版本解析。 什么是IOC容器? 容器,顧名思義可以用來容納一切事物。我們平常所說的Spring IOC容器就是一個(gè)可以容...

    不知名網(wǎng)友 評論0 收藏0
  • 零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)

    摘要:依賴注入是向某個(gè)類或方法注入一個(gè)值,其中所用到的原理就是控制反轉(zhuǎn)。但發(fā)現(xiàn)更多時(shí)間是在調(diào)和的源碼。里面就是從中取出這個(gè),完成控制反轉(zhuǎn)的。控制反轉(zhuǎn)的優(yōu)點(diǎn)最后來以我個(gè)人觀點(diǎn)談?wù)効刂品崔D(zhuǎn)的優(yōu)點(diǎn)吧。控制反轉(zhuǎn)為了降低項(xiàng)目耦合,提高延伸性。 本章開始來學(xué)習(xí)下Spring的源碼,看看Spring框架最核心、最常用的功能是怎么實(shí)現(xiàn)的。網(wǎng)上介紹Spring,說源碼的文章,大多數(shù)都是生搬硬推,都是直接看來的...

    wing324 評論0 收藏0
  • SpringBoot原理深入篇

    摘要:啟動原理和執(zhí)行原理分析一的啟動原理我們打開,注意看下面兩個(gè)依賴我們第一步是繼承了父項(xiàng)目,然后在添加啟動器的依賴,項(xiàng)目就會自動給我們導(dǎo)入關(guān)于項(xiàng)目所需要的配置和。 上一篇我們看到,我們很輕松的完成了項(xiàng)目的構(gòu)建,那么SpringBoot是如何做到的呢,在使用的使用又有哪些通用配置和注意事項(xiàng)呢? 其實(shí)SpringBoot給我們做了大量的自動配置功能,我們只需要引入對應(yīng)的啟動器就可以直接使用,作...

    gotham 評論0 收藏0

發(fā)表評論

0條評論

Big_fat_cat

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<