欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring中@Import的各種用法以及ImportAware接口詳解

 更新時(shí)間:2019年10月08日 11:15:15   作者:coder小黑  
這篇文章主要介紹了Spring中@Import的各種用法以及ImportAware接口詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

@Import 注解

@Import注解提供了和XML中<import/>元素等價(jià)的功能,實(shí)現(xiàn)導(dǎo)入的一個(gè)或多個(gè)配置類。@Import即可以在類上使用,也可以作為元注解使用。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

  /**
   * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
   * or regular component classes to import.
   */
  Class<?>[] value();

}

注解中只有一個(gè)value();。支持導(dǎo)入@Configuration標(biāo)注的配置類,實(shí)現(xiàn)ImportSelector接口的類、實(shí)現(xiàn)ImportBeanDefinitionRegistrar接口的類和普通的@component類。

作為元注解使用

@Import可以作為元注解使用,可以在@Import的繼承上封裝一層。我的理解是,這樣做不會(huì)對(duì)外(使用方)暴露我內(nèi)部的具體實(shí)現(xiàn)細(xì)節(jié)。

舉個(gè)例子:例如@EnableAspectJAutoProxy注解。

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

@EnableAspectJAutoProxy就是被@Import這個(gè)元注解所標(biāo)志了,我們(程序員)通過(guò)使用@EnableAspectJAutoProxy來(lái)開啟AspectJAutoProxy,而Spring底層是通過(guò)@Import導(dǎo)入相應(yīng)的配置類來(lái)實(shí)現(xiàn)的。

導(dǎo)入實(shí)現(xiàn)ImportSelector接口的類

先來(lái)看一下ImportSelector接口,該接口中只有一個(gè)方法:

public interface ImportSelector {
  String[] selectImports(AnnotationMetadata importingClassMetadata);
}

ImportSelector,輸入選擇器。該接口就是用來(lái)根據(jù)給定的條件,選擇導(dǎo)入哪些配置類。

舉個(gè)例子:例如@EnableTransactionManagement注解。

@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

在@EnableTransactionManagement注解中使用了@Import(TransactionManagementConfigurationSelector.class)注解,其中TransactionManagementConfigurationSelector類就是實(shí)現(xiàn)了ImportSelector接口。

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
  @Override
  protected String[] selectImports(AdviceMode adviceMode) {
    switch (adviceMode) {
      case PROXY:
        return new String[] {AutoProxyRegistrar.class.getName(),
            ProxyTransactionManagementConfiguration.class.getName()};
      case ASPECTJ:
        return new String[] {
            TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
      default:
        return null;
    }
  }
}

方法的內(nèi)部實(shí)現(xiàn)邏輯也很簡(jiǎn)單,就是根據(jù)不同的AdviceMode導(dǎo)入不同的配置類,來(lái)實(shí)現(xiàn)事務(wù)管理。

導(dǎo)入實(shí)現(xiàn)ImportBeanDefinitionRegistrar接口的類

ImportBeanDefinitionRegistrar接口中也只有一個(gè)方法:

public interface ImportBeanDefinitionRegistrar {
  void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}

該接口允許我們根據(jù)所給的注解元數(shù)據(jù),按需注冊(cè)額外的BeanDefinition。

舉個(gè)例子:例如@EnableAspectJAutoProxy注解。

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

@EnableAspectJAutoProxy注解引入了AspectJAutoProxyRegistrar.class類,這個(gè)類就是實(shí)現(xiàn)了ImportBeanDefinitionRegistrar接口。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

  @Override
  public void registerBeanDefinitions(
      AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

    AnnotationAttributes enableAspectJAutoProxy =
        AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
    if (enableAspectJAutoProxy != null) {
      if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
      }
      if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
        AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
      }
    }
  }
}

registerBeanDefinitions中調(diào)用了AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);方法,這個(gè)方法就是在往傳入的BeanDefinitionRegistry registry中注冊(cè)BeanDefinition。注冊(cè)了BeanDefinition之后,Spring就會(huì)去實(shí)例化這個(gè)Bean,從而達(dá)到AspectJAutoProxy作用。

導(dǎo)入@Configuration類

這次@Import最常見(jiàn)是使用方法。我們可以拆分配置類,然后在程序中按需導(dǎo)入相應(yīng)的配置。

舉個(gè)例子:例如@EnableRetry注解。使用這個(gè)注解可以開啟retry功能。

@EnableAspectJAutoProxy(proxyTargetClass = false)
@Import(RetryConfiguration.class)
public @interface EnableRetry {

其內(nèi)部就是導(dǎo)入了RetryConfiguration這個(gè)配置類。

ImportAware接口

ImportAware接口是需要和@Import一起使用的。在@Import作為元注解使用時(shí),通過(guò)@Import導(dǎo)入的配置類如果實(shí)現(xiàn)了ImportAware接口就可以獲取到導(dǎo)入該配置類接口的數(shù)據(jù)配置。有點(diǎn)繞,我們直接上代碼。

舉個(gè)例子:@EnableAsync注解。

@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
//AsyncConfigurationSelector源碼
public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {

  private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
      "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
  @Override
  @Nullable
  public String[] selectImports(AdviceMode adviceMode) {
    switch (adviceMode) {
      case PROXY:
        return new String[] {ProxyAsyncConfiguration.class.getName()};
      case ASPECTJ:
        return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
      default:
        return null;
    }
  }
}

默認(rèn)情況下使用AdviceMode為PROXY,導(dǎo)入了ProxyAsyncConfiguration類。

@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {

  @Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
    Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
    AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
    Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
    if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
      bpp.setAsyncAnnotationType(customAsyncAnnotation);
    }
    if (this.executor != null) {
      bpp.setExecutor(this.executor);
    }
    if (this.exceptionHandler != null) {
      bpp.setExceptionHandler(this.exceptionHandler);
    }
    bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
    bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
    return bpp;
  }
}

在ProxyAsyncConfiguration的asyncAdvisor方法中需要獲取到@EnableAsync上的一些設(shè)置值,例如:this.enableAsync.getBoolean("proxyTargetClass"),this.enableAsync.<Integer>getNumber("order")。

this.enableAsync是其父類AbstractAsyncConfiguration的屬性。AbstractAsyncConfiguration實(shí)現(xiàn)了ImportAware接口,從而就可以獲取到@EnableAsync上的信息了。

// AbstractAsyncConfiguration#setImportMetadata 源碼
public void setImportMetadata(AnnotationMetadata importMetadata) {
  this.enableAsync = AnnotationAttributes.fromMap(
      importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
  if (this.enableAsync == null) {
    throw new IllegalArgumentException(
        "@EnableAsync is not present on importing class " + importMetadata.getClassName());
  }
}

可能這個(gè)例子有點(diǎn)復(fù)雜的,還有一個(gè)稍微簡(jiǎn)單一點(diǎn)的例子:EnableRedisHttpSession。關(guān)于這個(gè),讀者可以自己去看一下源碼debug學(xué)習(xí)一下。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 推薦幾本學(xué)習(xí)java的書籍

    推薦幾本學(xué)習(xí)java的書籍

    本文給大家推薦了幾本學(xué)習(xí)Java的書籍,非常適合Java的初學(xué)者,有需要的朋友可以看看
    2014-10-10
  • springboot自定義yml配置文件及其外部部署過(guò)程

    springboot自定義yml配置文件及其外部部署過(guò)程

    這篇文章主要介紹了springboot自定義yml配置文件及其外部部署過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • SpringBoot如何用java生成靜態(tài)html

    SpringBoot如何用java生成靜態(tài)html

    這篇文章主要介紹了SpringBoot如何用java生成靜態(tài)html,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,需要的朋友可以參考一下
    2022-06-06
  • 出現(xiàn)java.lang.NoSuchMethodException異常的解決(靠譜)

    出現(xiàn)java.lang.NoSuchMethodException異常的解決(靠譜)

    這篇文章主要介紹了出現(xiàn)java.lang.NoSuchMethodException異常的解決方案(靠譜),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java實(shí)現(xiàn)求數(shù)組最長(zhǎng)子序列算法示例

    Java實(shí)現(xiàn)求數(shù)組最長(zhǎng)子序列算法示例

    這篇文章主要介紹了Java實(shí)現(xiàn)求數(shù)組最長(zhǎng)子序列算法,涉及java針對(duì)數(shù)組的遞歸遍歷、判斷相關(guān)操作技巧,需要的朋友可以參考下
    2018-07-07
  • Spring動(dòng)態(tài)注冊(cè)多數(shù)據(jù)源的實(shí)現(xiàn)方法

    Spring動(dòng)態(tài)注冊(cè)多數(shù)據(jù)源的實(shí)現(xiàn)方法

    這篇文章主要介紹了Spring動(dòng)態(tài)注冊(cè)多數(shù)據(jù)源的實(shí)現(xiàn)方法,小編覺(jué)的挺不錯(cuò)的,現(xiàn)分享到腳本之家平臺(tái),需要的朋友可以參考下
    2018-01-01
  • springmvc中進(jìn)行數(shù)據(jù)保存以及日期參數(shù)的保存過(guò)程解析

    springmvc中進(jìn)行數(shù)據(jù)保存以及日期參數(shù)的保存過(guò)程解析

    這篇文章主要介紹了springmvc中進(jìn)行數(shù)據(jù)保存以及日期參數(shù)的保存過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • SpringBoot?thymeleaf實(shí)現(xiàn)餅狀圖與柱形圖流程介紹

    SpringBoot?thymeleaf實(shí)現(xiàn)餅狀圖與柱形圖流程介紹

    這篇文章主要介紹了SpringBoot?thymeleaf實(shí)現(xiàn)餅狀圖與柱形圖流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2022-12-12
  • Java基礎(chǔ)之ClassLoader詳解

    Java基礎(chǔ)之ClassLoader詳解

    這篇文章主要介紹了Java基礎(chǔ)之ClassLoader詳解,文中對(duì)ClassLoader有非常詳細(xì)的解說(shuō),對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • SpringBoot如何優(yōu)雅地處理全局異常詳解

    SpringBoot如何優(yōu)雅地處理全局異常詳解

    這篇文章主要給大家介紹了關(guān)于SpringBoot如何優(yōu)雅地處理全局異常的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用SpringBoot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08

最新評(píng)論