成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

絕對讓你大開眼界的Spring依賴注入問題

開發 前端
本篇文章旨在深入探討將原型(Prototype)作用域的bean注入到單例(Singleton)作用域bean中的多種策略,并詳細剖析每種方法的優缺點。

環境:SpringBoot3.2.5

1. 簡介

本篇文章旨在深入探討將原型(Prototype)作用域的bean注入到單例(Singleton)作用域bean中的多種策略,并詳細剖析每種方法的優缺點。在Spring框架中,默認情況下bean是單例的,這意味著它們在應用的生命周期內僅被創建一次并共享。然而,當需要將原型bean(每次請求都創建一個新實例)注入到單例bean中時,就會出現作用域注入問題。如下示例:

@Configuration
public class AppConfig {
  @Bean
  @Scope(BeanDefinition.SCOPE_PROTOTYPE)
  public PrototypeBean prototypeBean() {
    return new PrototypeBean() ;
  }
  @Bean
  public SingletonBean singletonBean() {
    return new SingletonBean() ;
  }
}

在該配置類中,將PrototypeBean定義為原型bean,SingletonBean定義為單例,該單例bean的定義如下:

@Component
public class SingletonBean {


  @Resource
  private PrototypeBean prototypeBean ;  
  public void test() {
    System.out.println(this.prototypeBean) ;
  }
}

在這通過@Resource注解,注入原型bean。接下來我們通過如下的代碼進行測試:

ConfigurableApplicationContext context = SpringApplication.run(App.class, args) ;
SingletonBean bean = context.getBean(SingletonBean.class) ;
bean.test() ;
bean.test() ;
bean.test() ;

以上調用三次test方法,我們期望的是每次調用打印的prototypeBean屬性都不是同一個,結果如下:

com.pack.PrototypeBean@69fb6037
com.pack.PrototypeBean@69fb6037
com.pack.PrototypeBean@69fb6037

三次打印都是同一個。這種不同作用域的注入該如何解決呢?接下來我將介紹8種方式解決。

2. 解決辦法

2.1 單例bean實現ApplicationContextAware

public class SingletonBean implements ApplicationContextAware {
  private ApplicationContext context;
  public void test() {
    System.out.println(this.context.getBean(PrototypeBean.class)) ;
  }
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.context = applicationContext ;
  }
}

每調用test方法時都會通過ApplicationContext對象從容器中獲取新實例。

缺點:

  • 這種方法有個嚴重的缺點。它違背了控制權倒置的原則,因為我們直接向容器請求依賴關系。
  • 在SingletonBean類中通過applicationContext獲取原型 Bean。這意味著將代碼與 Spring 框架耦合。

除了這2缺點,用起來感覺還行啊

2.2 通過jakarta的Provider注入

public class SingletonBean {
  @Resource
  private jakarta.inject.Provider<PrototypeBean> provider ;
  public void test() {
    System.out.println(provider.get()) ;
  }
}

這里通過jakarta.inject包中的Provider接口注入原型bean。每次調用get方法都會從容器中再次獲取一個新的實例對象。

2.3 借助Spring提供的ObjectProvider接口

public class SingletonBean {
  @Resource
  private ObjectProvider<PrototypeBean> objectProvider ;
  public void test() {
    System.out.println(objectProvider.getIfAvailable()) ;
  }
}

直接注入ObjectProvider接口對象,該接口提供了豐富的方法,不僅僅可以獲取單個對象,也可以獲取多個對象(集合),包括如下可用方法:

圖片圖片

2.4 借助Spring的ObjectFactory接口

public class SingletonBean {
  @Resource
  private ObjectFactory<PrototypeBean> objectFactory ;
  public void test() {
    System.out.println(objectFactory.getObject()) ;
  }
}

該接口與上面ObjectProvider接口挺像,但是ObjectFactory是函數式接口只有一個getObject方法,并且只能返回一個對象。

2.5 使用@Lookup注解

public class SingletonBean {
  
  public void test() {
    System.out.println(get()) ;
  }
  @Lookup
  protected PrototypeBean get() {
    return null ;
  }
}

Spring 會將SingletonBean創建為代理對象并覆蓋使用 @Lookup 注解的 get() 方法。每當我們調用get() 方法時,它會返回一個新的 PrototypeBean 實例。

2.6 注冊Function類型的Bean

@Bean
public <T> Function<Class<T>, T> targetBean(ApplicationContext context) {
  return t -> context.getBean(t) ;
}

這里注冊了Function類型的bean對象,而具體會是什么類型完全由使用的地方決定。

public class SingletonBean {
  @Resource
  private Function<Class<?>, PrototypeBean> targetBean ;
  public void test() {
    System.out.println(targetBean.apply(PrototypeBean.class)) ;
  }
}

通過定義Function類型的bean,這里我們就可以不限制具體是那個類型的原型bean,這就非常的通用了。

2.7 作用域代理

@Component
@Scope(value = BeanDefinition.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class PrototypeBean {
}

在@Scope注解上配置proxyMode=TARGET_CLASS這樣配置以后,容器將會為PrototypeBean創建代理對象。也是能夠保證每次獲取的都是新的實例對象。

2.8 使用@Lazy注解

public class SingletonBean {
  @Resource
  @Lazy
  private PrototypeBean prototypeBean ;
}

通過@Lazy注解后,這里注入的PrototypeBean將會是一個代理對象,這樣也可以保證每次使用時都是新的實例對象。

責任編輯:武曉燕 來源: Spring全家桶實戰案例源碼
相關推薦

2024-06-06 08:06:26

2021-04-03 13:12:43

微信技巧Bug

2021-01-10 08:16:25

微信移動應用實用技巧

2018-02-25 08:48:50

百度職業代碼

2020-09-17 20:25:00

人工智能

2014-04-01 11:39:38

集裝箱數據中心谷歌

2025-03-31 08:10:43

2010-12-20 13:53:10

GoogleWebGL

2009-05-19 10:18:00

機房網絡管理

2020-04-06 09:21:04

AI醫療汽車行業

2021-01-12 05:57:49

AI人工智能機器學習

2011-04-13 14:52:13

Qcon

2021-12-23 20:00:59

Firefox瀏覽器開源

2018-04-25 10:46:05

Linux命令行日歷

2021-12-20 10:32:05

IT技術領導者CIO

2025-03-24 08:11:20

技巧CSS編輯器

2024-01-15 07:00:00

2024-12-16 08:11:45

Python系統調用

2013-01-22 16:39:44

NFC移動支付

2021-12-28 11:06:22

Python 開發編程語言
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲二区视频 | 国产精品久久久久aaaa | 精品国产99 | 欧美日韩久久精品 | 欧美高清视频 | 亚洲一区二区三区视频 | 免费黄色片在线观看 | 天天久久 | 精品国产伦一区二区三区观看体验 | 国产特级毛片aaaaaa | 国产三级一区二区三区 | 亚洲高清视频在线观看 | 久久精品国产99国产精品 | 日韩欧美国产精品综合嫩v 一区中文字幕 | 亚洲欧美视频一区 | 国产精品中文字幕在线 | 资源首页二三区 | 99re国产视频 | 91亚洲一区 | 欧美一区二区大片 | 亚洲二区视频 | 一区二区三区国产精品 | 日韩国产免费观看 | 99久久久国产精品免费消防器 | 黄色免费观看网站 | 日本又色又爽又黄的大片 | 毛片在线免费 | 精品国产一二三区 | 国产日产欧产精品精品推荐蛮挑 | 天天成人综合网 | av电影一区二区 | 国产999精品久久久 日本视频一区二区三区 | 亚洲精品国产第一综合99久久 | 久久99精品国产 | 国产精品视频综合 | 午夜视频免费在线观看 | 成人网在线观看 | 日韩一区二区三区四区五区 | 亚洲一区二区三区在线视频 | 狠狠久| 久久久妇女国产精品影视 |