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

資訊專欄INFORMATION COLUMN

Spring中接口動態(tài)實現(xiàn)的解決方案

ispring / 1659人閱讀

摘要:聲明解決方案是基于源碼,進(jìn)行二次開發(fā)實現(xiàn)。其是基于層面,不存在任何的接口實現(xiàn)類。因而在實現(xiàn)的過程中,首先要解決的是如何動態(tài)實現(xiàn)接口的實例化。其次是如何將使接口根據(jù)注解實現(xiàn)相應(yīng)的功能。

聲明解決方案是基于Mybatis源碼,進(jìn)行二次開發(fā)實現(xiàn)。

問題領(lǐng)導(dǎo)最近跟我提了一個需求,是有關(guān)于實現(xiàn)類Mybatis的@Select、@Insert注解的功能。其是基于interface層面,不存在任何的接口實現(xiàn)類。因而在實現(xiàn)的過程中,首先要解決的是如何動態(tài)實現(xiàn)接口的實例化。其次是如何將使接口根據(jù)注解實現(xiàn)相應(yīng)的功能。

我們先來看看Mybatis是如何實現(xiàn)Dao類的掃描的。

MapperScannerConfigurer.java

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    if (this.processPropertyPlaceHolders) {
      processPropertyPlaceHolders();
    }

    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
    scanner.setAddToConfig(this.addToConfig);
    scanner.setAnnotationClass(this.annotationClass);
    scanner.setMarkerInterface(this.markerInterface);
    scanner.setSqlSessionFactory(this.sqlSessionFactory);
    scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
    scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
    scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
    scanner.setResourceLoader(this.applicationContext);
    scanner.setBeanNameGenerator(this.nameGenerator);
    scanner.registerFilters();
    scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
  }

ClassPathMapperScanner是Mybatis繼承ClassPathBeanDefinitionScanner類而來的。這里對于ClassPathMapperScanner的配置參數(shù)來源于我們在使用Mybatis時的配置而來,是不是還記得在使用Mybatis的時候要配置basePackage的參數(shù)呢?

接著我們就順著scanner.scan()方法,進(jìn)入查看一下里面的實現(xiàn)。

ClassPathBeanDefinitionScanner.java

public int scan(String... basePackages) {
   int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

   doScan(basePackages);

   // Register annotation config processors, if necessary.
   if (this.includeAnnotationConfig) {
      AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
   }

   return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}

這里關(guān)鍵的代碼是doScan(basePackages);,那么我們在進(jìn)去看一下。可能你會看到的是Spring源碼的實現(xiàn)方法,但這里Mybatis也實現(xiàn)了自己的一套,我們看一下Mybatis的實現(xiàn)。

ClassPathMapperScanner.java

public Set doScan(String... basePackages) {
  Set beanDefinitions = super.doScan(basePackages);

  if (beanDefinitions.isEmpty()) {
    logger.warn("No MyBatis mapper was found in "" + Arrays.toString(basePackages) + "" package. Please check your configuration.");
  } else {
    for (BeanDefinitionHolder holder : beanDefinitions) {
      GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();

      if (logger.isDebugEnabled()) {
        logger.debug("Creating MapperFactoryBean with name "" + holder.getBeanName() 
            + "" and "" + definition.getBeanClassName() + "" mapperInterface");
      }

      // the mapper interface is the original class of the bean
      // but, the actual class of the bean is MapperFactoryBean
      definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName());
      definition.setBeanClass(MapperFactoryBean.class);

      definition.getPropertyValues().add("addToConfig", this.addToConfig);

      boolean explicitFactoryUsed = false;
      if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
        definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
        explicitFactoryUsed = true;
      } else if (this.sqlSessionFactory != null) {
        definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
        explicitFactoryUsed = true;
      }

      if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
        if (explicitFactoryUsed) {
          logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
        }
        definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
        explicitFactoryUsed = true;
      } else if (this.sqlSessionTemplate != null) {
        if (explicitFactoryUsed) {
          logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
        }
        definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
        explicitFactoryUsed = true;
      }

      if (!explicitFactoryUsed) {
        if (logger.isDebugEnabled()) {
          logger.debug("Enabling autowire by type for MapperFactoryBean with name "" + holder.getBeanName() + "".");
        }
        definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
      }
    }
  }

  return beanDefinitions;
}

definition.setBeanClass(MapperFactoryBean.class);這行代碼是非常關(guān)鍵的一句,由于在Spring中存在兩種自動實例化的方式,一種是我們常用的本身的接口實例化類進(jìn)行接口實例化,還有一種就是這里的自定義實例化。而這里的setBeanClass方法就是在BeanDefinitionHolder中進(jìn)行配置。在Spring進(jìn)行實例化的時候進(jìn)行處理。

那么我們在看一下MapperFactoryBean.class

MapperFactoryBean.java

public class MapperFactoryBean extends SqlSessionDaoSupport implements FactoryBean {

  private Class mapperInterface;

  private boolean addToConfig = true;

  /**
   * Sets the mapper interface of the MyBatis mapper
   *
   * @param mapperInterface class of the interface
   */
  public void setMapperInterface(Class mapperInterface) {
    this.mapperInterface = mapperInterface;
  }

  /**
   * If addToConfig is false the mapper will not be added to MyBatis. This means
   * it must have been included in mybatis-config.xml.
   * 

* If it is true, the mapper will be added to MyBatis in the case it is not already * registered. *

* By default addToCofig is true. * * @param addToConfig */ public void setAddToConfig(boolean addToConfig) { this.addToConfig = addToConfig; } /** * {@inheritDoc} */ @Override protected void checkDaoConfig() { super.checkDaoConfig(); notNull(this.mapperInterface, "Property "mapperInterface" is required"); Configuration configuration = getSqlSession().getConfiguration(); if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) { try { configuration.addMapper(this.mapperInterface); } catch (Throwable t) { logger.error("Error while adding the mapper "" + this.mapperInterface + "" to configuration.", t); throw new IllegalArgumentException(t); } finally { ErrorContext.instance().reset(); } } } /** * {@inheritDoc} */ public T getObject() throws Exception { return getSqlSession().getMapper(this.mapperInterface); } /** * {@inheritDoc} */ public Class getObjectType() { return this.mapperInterface; } /** * {@inheritDoc} */ public boolean isSingleton() { return true; }

在該類中其實現(xiàn)了FactoryBean接口,看過Spring源碼的人,我相信對其都有很深的印象,其在Bean的實例化中起著很重要的作用。在該類中我們要關(guān)注的是getObject方法,我們之后將動態(tài)實例化的接口對象放到Spring實例化列表中,這里就是入口,也是我們的起點。不過要特別說明的是mapperInterface的值是如何被賦值的,可能會有疑問,我們再來看看上面的ClassPathMapperScanner.java我們在配置MapperFactoryBean.class的上面存在一行 definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName());其在之后在Spring的PostProcessorRegistrationDelegate類的populateBean方法中進(jìn)行屬性配置,會將其依靠反射的方式將其注入到MapperFactoryBean.class中。

而且definition.getPropertyValues().add中添加的值是注入到MapperFactoryBean對象中去的。這一點需要說明一下。

更多內(nèi)容可以關(guān)注微信公眾號,或者訪問AppZone網(wǎng)站

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

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

相關(guān)文章

  • Spring自定義注解不生效原因解析及解決方法

    摘要:自定義注解不生效原因解析及解決方法背景項目中,自己基于實現(xiàn)了一套緩存注解。但是最近出現(xiàn)一種情況緩存竟然沒有生效,大量請求被擊穿到層,導(dǎo)致壓力過大。至此,問題得到解決。 自定義注解不生效原因解析及解決方法 背景: 項目中,自己基于spring AOP實現(xiàn)了一套java緩存注解。但是最近出現(xiàn)一種情況:緩存竟然沒有生效,大量請求被擊穿到db層,導(dǎo)致db壓力過大。現(xiàn)在我們看一下具體代碼情形(代...

    xbynet 評論0 收藏0
  • 【好好面試】學(xué)完Aop,連動態(tài)代理原理都不懂?

    摘要:總結(jié)動態(tài)代理的相關(guān)原理已經(jīng)講解完畢,接下來讓我們回答以下幾個思考題。 【干貨點】 此處是【好好面試】系列文的第12篇文章。文章目標(biāo)主要是通過原理剖析的方式解答Aop動態(tài)代理的面試熱點問題,通過一步步提出問題和了解原理的方式,我們可以記得更深更牢,進(jìn)而解決被面試官卡住喉嚨的情況。問題如下 SpringBoot默認(rèn)代理類型是什么 為什么不用靜態(tài)代理 JDK動態(tài)代理原理 CGLIB動態(tài)代理...

    Keven 評論0 收藏0
  • 慕課網(wǎng)_《Spring入門篇》學(xué)習(xí)總結(jié)

    摘要:入門篇學(xué)習(xí)總結(jié)時間年月日星期三說明本文部分內(nèi)容均來自慕課網(wǎng)。主要的功能是日志記錄,性能統(tǒng)計,安全控制,事務(wù)處理,異常處理等等。 《Spring入門篇》學(xué)習(xí)總結(jié) 時間:2017年1月18日星期三說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:https://github.com/zccodere/s...個人學(xué)習(xí)源碼:https://git...

    Ververica 評論0 收藏0
  • Spring AOP就是這么簡單啦

    摘要:是一種特殊的增強切面切面由切點和增強通知組成,它既包括了橫切邏輯的定義也包括了連接點的定義。實際上,一個的實現(xiàn)被拆分到多個類中在中聲明切面我們知道注解很方便,但是,要想使用注解的方式使用就必須要有源碼因為我們要 前言 只有光頭才能變強 上一篇已經(jīng)講解了Spring IOC知識點一網(wǎng)打盡!,這篇主要是講解Spring的AOP模塊~ 之前我已經(jīng)寫過一篇關(guān)于AOP的文章了,那篇把比較重要的知...

    Jacendfeng 評論0 收藏0
  • 學(xué)Aop?看這篇文章就夠了!!!

    摘要:又是什么其實就是一種實現(xiàn)動態(tài)代理的技術(shù),利用了開源包,先將代理對象類的文件加載進(jìn)來,之后通過修改其字節(jié)碼并且生成子類。 在實際研發(fā)中,Spring是我們經(jīng)常會使用的框架,畢竟它們太火了,也因此Spring相關(guān)的知識點也是面試必問點,今天我們就大話Aop。特地在周末推文,因為該篇文章閱讀起來還是比較輕松詼諧的,當(dāng)然了,更主要的是周末的我也在充電學(xué)習(xí),希望有追求的朋友們也盡量不要放過周末時...

    boredream 評論0 收藏0

發(fā)表評論

0條評論

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