最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實現(xiàn)ImportBeanDefinitionRegistrar動態(tài)注入

 更新時間:2024年02月19日 09:38:25   作者:清醒的人最荒唐  
在閱讀Spring Boot源碼時,看到Spring Boot中大量使用ImportBeanDefinitionRegistrar來實現(xiàn)Bean的動態(tài)注入,它是Spring中一個強大的擴展接口,本文就來詳細的介紹一下如何使用,感興趣的可以了解一下

在閱讀Spring Boot源碼時,看到Spring Boot中大量使用ImportBeanDefinitionRegistrar來實現(xiàn)Bean的動態(tài)注入。它是Spring中一個強大的擴展接口。本篇文章來講講它相關(guān)使用。

Spring Boot中的使用

在Spring Boot 內(nèi)置容器的相關(guān)自動配置中有一個ServletWebServerFactoryAutoConfiguration類。該類的部分代碼如下:

@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
    ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
    ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
    ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {

  // ...
  
  /**
   * Registers a {@link WebServerFactoryCustomizerBeanPostProcessor}. Registered via
   * {@link ImportBeanDefinitionRegistrar} for early registration.
   */
  public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {

    private ConfigurableListableBeanFactory beanFactory;

    // 實現(xiàn)BeanFactoryAware的方法,設(shè)置BeanFactory
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
      if (beanFactory instanceof ConfigurableListableBeanFactory) {
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
      }
    }

    // 注冊一個WebServerFactoryCustomizerBeanPostProcessor
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
        BeanDefinitionRegistry registry) {
      if (this.beanFactory == null) {
        return;
      }
      registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
          WebServerFactoryCustomizerBeanPostProcessor.class);
      registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",
          ErrorPageRegistrarBeanPostProcessor.class);
    }

    // 檢查并注冊Bean
    private void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name, Class<?> beanClass) {
      // 檢查指定類型的Bean name數(shù)組是否存在,如果不存在則創(chuàng)建Bean并注入到容器中
      if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
        beanDefinition.setSynthetic(true);
        registry.registerBeanDefinition(name, beanDefinition);
      }
    }
  }

在這個自動配置類中,基本上展示了ImportBeanDefinitionRegistrar最核心的用法。這里該接口主要用來注冊BeanDefinition。

BeanPostProcessorsRegistrar實現(xiàn)了ImportBeanDefinitionRegistrar接口和BeanFactoryAware接口。其中BeanFactoryAware接口的實現(xiàn)是用來暴露Spring的ConfigurableListableBeanFactory對象。

而實現(xiàn)registerBeanDefinitions方法則是用來對Bean的動態(tài)注入,這里注入了WebServerFactoryCustomizerBeanPostProcessor和ErrorPageRegistrarBeanPostProcessor。

簡單了解了Spring Boot中的一個使用實例,下面我們總結(jié)一下使用方法,并自己實現(xiàn)一個類似的功能。

ImportBeanDefinitionRegistrar使用

Spring官方通過ImportBeanDefinitionRegistrar實現(xiàn)了@Component、@Service等注解的動態(tài)注入機制。

很多三方框架集成Spring的時候,都會通過該接口,實現(xiàn)掃描指定的類,然后注冊到spring容器中。 比如Mybatis中的Mapper接口,springCloud中的FeignClient接口,都是通過該接口實現(xiàn)的自定義注冊邏輯。

所有實現(xiàn)了該接口的類的都會被ConfigurationClassPostProcessor處理,ConfigurationClassPostProcessor實現(xiàn)了BeanFactoryPostProcessor接口,所以ImportBeanDefinitionRegistrar中動態(tài)注冊的bean是優(yōu)先于依賴其的bean初始化,也能被aop、validator等機制處理。

基本步驟:

  • 實現(xiàn)ImportBeanDefinitionRegistrar接口;
  • 通過registerBeanDefinitions實現(xiàn)具體的類初始化;
  • 在@Configuration注解的配置類上使用@Import導入實現(xiàn)類;

簡單示例

這里實現(xiàn)一個非常簡單的操作,自定義一個@Mapper注解(并非Mybatis中的Mapper實現(xiàn)),實現(xiàn)類似@Component的功能,添加了@Mapper注解的類會被自動加載到spring容器中。

首先創(chuàng)建@Mapper注解。

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
public @interface Mapper {
}

創(chuàng)建UserMapper類,用于使用@Mapper注。

@Mapper
public class UserMapper {
}

定義ImportBeanDefinitionRegistrar的實現(xiàn)類MapperAutoConfigureRegistrar。如果需要獲取Spring中的一些數(shù)據(jù),可實現(xiàn)一些Aware接口,這實現(xiàn)了ResourceLoaderAware。

public class MapperAutoConfigureRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
  
  private ResourceLoader resourceLoader;

  @Override
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    MapperBeanDefinitionScanner scanner = new MapperBeanDefinitionScanner(registry, false);
    scanner.setResourceLoader(resourceLoader);
    scanner.registerFilters();
    scanner.addIncludeFilter(new AnnotationTypeFilter(Mapper.class));
    scanner.doScan("com.secbro2.learn.mapper");
  }

  @Override
  public void setResourceLoader(ResourceLoader resourceLoader) {
    this.resourceLoader = resourceLoader;
  }
}

在上面代碼中,通過ResourceLoaderAware接口的setResourceLoader方法獲得到了ResourceLoader對象。

在registerBeanDefinitions方法中,借助ClassPathBeanDefinitionScanner類的實現(xiàn)類來掃描獲取需要注冊的Bean。

MapperBeanDefinitionScanner的實現(xiàn)如下:

public class MapperBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {

  public MapperBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
    super(registry, useDefaultFilters);
  }

  protected void registerFilters() {
    addIncludeFilter(new AnnotationTypeFilter(Mapper.class));
  }

  @Override
  protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    return super.doScan(basePackages);
  }
}

MapperBeanDefinitionScanner繼承子ClassPathBeanDefinitionScanner,掃描被@Mapper的注解的類。

MapperBeanDefinitionScanner中指定了addIncludeFilter方法的參數(shù)為包含Mapper的AnnotationTypeFilter。

當然也可以通過excludeFilters指定不加載的類型。這兩個方法由它們的父類ClassPathScanningCandidateComponentProvider提供的。

完成了上面的定義,則進行最后一步引入操作了。創(chuàng)建一個自動配置類MapperAutoConfig,并通過@Import引入自定義的Registrar。

@Configuration
@Import(MapperAutoConfigureRegistrar.class)
public class MapperAutoConfig {
}

至此,整個代碼的功能已經(jīng)編寫完成,下面寫一個單元測試。

@RunWith(SpringRunner.class)
@SpringBootTest
public class MapperAutoConfigureRegistrarTest {

  @Autowired
  UserMapper userMapper;

  @Test
  public void contextLoads() {
    System.out.println(userMapper.getClass());
  }
}

執(zhí)行單元測試代碼,會發(fā)現(xiàn)打印如下日志:

class com.edu.mapper.UserMapper

當然,這里的UserMapper并不是接口,這里的實現(xiàn)也并不是Mybatis中的實現(xiàn)形式。只是為了演示該功能的簡單示例。需要注意的是文中提到了兩種實現(xiàn)的實例,第一種是Spring Boot中的實現(xiàn),第二種是我們的Mapper實例。展現(xiàn)了兩種不同方法的注冊的操作,但整個使用流程是一致的,讀者注意仔細品味,并在此基礎(chǔ)上進行拓展更復(fù)雜的功能。

到此這篇關(guān)于SpringBoot實現(xiàn)ImportBeanDefinitionRegistrar動態(tài)注入的文章就介紹到這了,更多相關(guān)SpringBoot 動態(tài)注入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java圖形界面之JFrame,JLabel,JButton詳解

    Java圖形界面之JFrame,JLabel,JButton詳解

    這篇文章主要介紹了Java圖形界面之JFrame、JLabel、JButton詳解,文中有非常詳細的代碼示例,對正在學習java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • Java編程調(diào)用微信支付功能的方法詳解

    Java編程調(diào)用微信支付功能的方法詳解

    這篇文章主要介紹了Java編程調(diào)用微信支付功能的方法,結(jié)合實例形式詳細分析了java微信支付功能的原理、操作流程及相關(guān)實現(xiàn)技巧,需要的朋友可以參考下
    2017-08-08
  • Java詳解HashMap實現(xiàn)原理和源碼分析

    Java詳解HashMap實現(xiàn)原理和源碼分析

    這篇文章主要介紹了Java關(guān)于HashMap的實現(xiàn)原理并進行源碼分析,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • java實現(xiàn)學生教師管理系統(tǒng)

    java實現(xiàn)學生教師管理系統(tǒng)

    這篇文章主要為大家詳細介紹了java實現(xiàn)學生教師管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • spring事務(wù)隔離級別、傳播機制以及簡單配置方式

    spring事務(wù)隔離級別、傳播機制以及簡單配置方式

    這篇文章主要介紹了spring事務(wù)隔離級別、傳播機制以及簡單配置方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • 帶你了解Java中的Mono接口

    帶你了解Java中的Mono接口

    Mono是ProjectReactor庫的核心類型之一,用于處理0或1個元素的異步數(shù)據(jù)流,本文主要介紹了帶你了解Java中的Mono接口,具有一定的參考價值,感興趣的可以了解一下
    2026-04-04
  • Eureka源碼閱讀之環(huán)境搭建及工程結(jié)構(gòu)

    Eureka源碼閱讀之環(huán)境搭建及工程結(jié)構(gòu)

    這篇文章主要為大家介紹了Eureka源碼閱讀之環(huán)境搭建的工程結(jié)構(gòu)及調(diào)試需知詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪<BR>
    2022-10-10
  • 淺談Spring Context加載方式

    淺談Spring Context加載方式

    這篇文章主要介紹了淺談Spring Context加載方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • SpringBoot集成緩存功能詳解

    SpringBoot集成緩存功能詳解

    Java?Caching定義了五個核心接口,分別是:CachingProvider、CacheManager、Cache、Entry和Expiry,這篇文章主要介紹了SpringBoot集成緩存功能詳細過程,需要的朋友可以參考下
    2024-06-06
  • SpringBoot異步Async使用Future與CompletableFuture區(qū)別小結(jié)

    SpringBoot異步Async使用Future與CompletableFuture區(qū)別小結(jié)

    本文主要介紹了SpringBoot異步Async使用Future與CompletableFuture區(qū)別小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06

最新評論

浦北县| 武清区| 丹巴县| 隆尧县| 上栗县| 广饶县| 商河县| 嘉禾县| 伊春市| 吐鲁番市| 湘潭县| 伊川县| 定襄县| 江口县| 东山县| 海晏县| 岢岚县| 元谋县| 平阳县| 乡城县| 阿拉善左旗| 陆河县| 琼结县| 循化| 安新县| 夏邑县| 临高县| 英吉沙县| 清丰县| 黄石市| 青州市| 巴东县| 石台县| 浙江省| 贡觉县| 昌都县| 六安市| 龙胜| 德阳市| 武清区| 临桂县|