自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

考察你對(duì) Spring 基本功掌握能力

開(kāi)發(fā) 前端
在 Spring Boot 應(yīng)用程序中,有時(shí)需要為同一個(gè)類創(chuàng)建多個(gè)實(shí)例(Bean),并且每個(gè)實(shí)例可能有不同的配置或用途。雖然可以通過(guò)在 @Configuration 配置類中定義多個(gè) @Bean 方法來(lái)實(shí)現(xiàn)這一點(diǎn),但在需要?jiǎng)?chuàng)建大量實(shí)例的情況下,這種方法不僅冗余,而且難以維護(hù)。

1. 簡(jiǎn)介

在 Spring Boot 應(yīng)用程序中,有時(shí)需要為同一個(gè)類創(chuàng)建多個(gè)實(shí)例(Bean),并且每個(gè)實(shí)例可能有不同的配置或用途。雖然可以通過(guò)在 @Configuration 配置類中定義多個(gè) @Bean 方法來(lái)實(shí)現(xiàn)這一點(diǎn),但在需要?jiǎng)?chuàng)建大量實(shí)例的情況下,這種方法不僅冗余,而且難以維護(hù)。

在本篇文章中,我們將學(xué)習(xí)如何在Spring框架中使用注解來(lái)創(chuàng)建同一類的多個(gè)beans。

2. 實(shí)戰(zhàn)案例

2.1 使用Java配置

這是使用注解創(chuàng)建多個(gè)同類 bean 的最簡(jiǎn)單易行的方法。在這種方法中,我們將使用基于 Java 的配置類來(lái)配置同一類中的多個(gè) Bean,如下示例:

public class Person {
  private String name ;
  private Integer age ;


  public Person(String name, Integer age) {
    this.name = name ;
    this.age = age ;
  }
  // getters, setters
  @Override
  public String toString() {
    return "Person [name=" + name+ ", age=" + age+ "]" ;
  }
}

接下來(lái),我們將構(gòu)建一個(gè)名為 PersonConfig 的配置類,并在其中定義 Person 類的多個(gè) Bean:

@Configuration
public class PersonConfig {
  @Bean
  public Person person1() {
    return new Person("Pack", 22) ;
  }


  @Bean
  public Person person2() {
    return new Person("xxgg", 24) ;
  }
}

在這里,@Bean 注解實(shí)例化兩個(gè)bean,并將它們注冊(cè)到Spring容器中。接下來(lái),我們可以初始化Spring容器,并從Spring容器中請(qǐng)求任何bean。這種策略還使得實(shí)現(xiàn)依賴注入變得簡(jiǎn)單。我們可以使用自動(dòng)裝配直接將一個(gè)bean(例如person1)注入到同類型的另一個(gè)bean(例如person2)中。

這種方法的局限是,在典型的基于Java的配置風(fēng)格中,我們需要使用new關(guān)鍵字手動(dòng)實(shí)例化bean。因此,如果相同類的bean數(shù)量增加,我們需要先注冊(cè)它們,并在配置類中創(chuàng)建這些bean。這使得它成為一種更偏向于Java的方法,而不是Spring特有的方法。

2.2 使用@Component注解

在這種方法中,我們將使用@Component注解來(lái)創(chuàng)建多個(gè)bean,這些bean將從Person類繼承屬性。首先,我們將創(chuàng)建多個(gè)子類,即PersonOne和PersonTwo,它們擴(kuò)展自Person超類:

@Component
public class PersonOne extends Person {


  public PersonOne() {
    super("Pack", 22) ;
  }
}
@Component
public class PersonTwo extends Person {


  public PersonTwo() {
    super("xxxooo", 24) ;
  }
}

這種方法的問(wèn)題是,它不會(huì)為同一個(gè)類創(chuàng)建多個(gè)實(shí)例。相反,它創(chuàng)建的是從超類繼承屬性的類的bean。因此,我們只能在繼承類沒(méi)有定義任何額外屬性的情況下使用這種解決方案。此外,使用繼承會(huì)增加代碼的整體復(fù)雜性。

2.3 使用BeanFactoryPostProcessor

利用 BeanFactoryPostProcessor 接口的自定義實(shí)現(xiàn)來(lái)創(chuàng)建同一類的多個(gè) Bean 實(shí)例。我們將通過(guò)以下步驟來(lái)實(shí)現(xiàn):

  • 創(chuàng)建自定義 Bean 類并使用 FactoryBean 接口對(duì)其進(jìn)行配置
  • 使用 BeanFactoryPostProcessor 接口實(shí)例化同一類型的多個(gè) Bean 

自定義 Bean 實(shí)現(xiàn)

為了更好地理解這種方法,我們將進(jìn)一步擴(kuò)展同一實(shí)力。假設(shè)有一個(gè) Human 類,它依賴于 Person 類的多個(gè)實(shí)例:

public class Human implements InitializingBean {


  private Person personOne;
  private Person personTwo;


  @Override
  public void afterPropertiesSet() throws Exception {
    Assert.notNull(personOne, "Pack is alive!");
    Assert.notNull(personTwo, "Jook is alive!");
  }
  @Autowired
  public void setPersonOne(Person personOne) {
    this.personOne = personOne ;
    this.personOne.setName("Pack") ;
    this.personOne.setAge(22) ;
  }
  @Autowired
  public void setPersonTwo(Person personTwo) {
    this.personTwo = personTwo ;
    this.personTwo.setName("Jook") ;
    this.personTwo.setAge(24) ;
  }
}

InitializingBean 接口會(huì)調(diào)用 afterPropertiesSet() 方法來(lái)檢查 BeanFactory 是否設(shè)置了所有 Bean 屬性,以及是否滿足了其他依賴條件。此外,我們將使用setter注入法注入并初始化兩個(gè) Person 類 Bean:personOne 和 personTwo。接下來(lái),我們將創(chuàng)建一個(gè)實(shí)現(xiàn) FactoryBean 接口的 Person 類。

@Qualifier(value = "personOne, personTwo")
public class Person implements FactoryBean<Object> {
  private String name ;
  private Integer age ;


  public Person() {
  }
  public Class<Person> getObjectType() {
      return Person.class ;
  }
  public Object getObject() throws Exception {
      return new Person() ;
  }
  public boolean isSingleton() {
      return true ;
  }
}

這里要注意的是 @Qualifier 注解的使用,它包含了類級(jí)別上多個(gè) Person 類型的名稱或 bean id。在這種情況下,在類級(jí)別使用 @Qualifier 是有原因的,我們接下來(lái)就會(huì)看到。

自定義 BeanFactory 實(shí)現(xiàn)

任何實(shí)現(xiàn) BeanFactoryPostProcessor 的類都會(huì)在創(chuàng)建任何 Spring Bean 之前執(zhí)行。BeanFactoryPostProcessor 會(huì)掃描所有使用 @Qualifier 注釋的類。此外,它還會(huì)從注解中提取名稱(Bean ID),并用指定的名稱手動(dòng)創(chuàng)建該類類型的實(shí)例:

public class PersonFactoryPostProcessor implements BeanFactoryPostProcessor {


  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    Map<String, Object> map = beanFactory.getBeansWithAnnotation(Qualifier.class) ;
    for (Map.Entry<String, Object> entry : map.entrySet()) {
      createInstances(beanFactory, entry.getKey(), entry.getValue()) ;
    }
  }


  private void createInstances(ConfigurableListableBeanFactory beanFactory, String beanName, Object bean) {
    Qualifier qualifier = bean.getClass().getAnnotation(Qualifier.class) ;
    for (String name : extractNames(qualifier)) {
      Object newBean = beanFactory.getBean(beanName) ;
      beanFactory.registerSingleton(name.trim(), newBean) ;
    }
  }


  private String[] extractNames(Qualifier qualifier) {
    return qualifier.value().split(",") ;
  }
}

在這里,自定義 BeanFactoryPostProcessor 實(shí)現(xiàn)會(huì)在 Spring 容器初始化后被調(diào)用。

最后,配置上面定義的Human及BeanFactoryPostProcessor

@Configuration
public class PersonConfig {
  @Bean
  public PersonFactoryPostProcessor PersonFactoryPostProcessor() {
    return new PersonFactoryPostProcessor();
  }
  @Bean
  public Person person() {
    return new Person() ;
  }
  @Bean
  public Human human() {
    return new Human() ;
  }
}

這種方法的局限性在于其復(fù)雜性。所以不鼓勵(lì)使用這種方法。盡管有其局限性,但這種方法更符合 Spring 的特性,可以使用注解實(shí)例化多個(gè)相似類型的 Bean。

責(zé)任編輯:武曉燕 來(lái)源: Spring全家桶實(shí)戰(zhàn)案例源碼
相關(guān)推薦

2010-09-26 08:56:10

Oracle

2014-11-20 14:39:12

網(wǎng)絡(luò)傳輸

2024-08-29 08:36:32

2020-10-21 09:18:50

程序員前端Github

2009-10-10 16:57:33

布線工藝要求

2015-01-15 09:21:24

TCP窗口

2020-11-20 14:16:20

Python開(kāi)發(fā)表格

2022-03-31 15:17:04

JavaSocketServlet容器

2017-04-12 10:40:34

公有云

2020-11-06 09:05:18

前端web開(kāi)發(fā)

2011-07-22 16:43:37

java

2017-02-27 21:30:29

數(shù)據(jù)中心光纖電纜

2011-11-28 09:26:57

2020-12-07 10:38:13

Python開(kāi)發(fā)語(yǔ)言

2023-06-28 11:58:00

2020-09-16 14:17:42

flat方法

2023-06-25 08:38:09

多線程循環(huán)打印

2009-11-10 11:54:12

VB.NET按鈕

2025-04-11 07:50:00

虛析構(gòu)函數(shù)C++開(kāi)發(fā)

2010-06-28 21:33:17

eMule協(xié)議
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)