AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

如何讓 Bean 深度感知 Spring 容器

來源: 責編: 時間:2023-11-03 09:16:52 300觀看
導讀Spring 有一個特點,就是創建出來的 Bean 對容器是無感的,一個 Bean 是怎么樣被容器從一個 Class 整成一個 Bean 的,對于 Bean 本身來說是不知道的,當然也不需要知道,也就是 Bean 對容器的存在是無感的。但是有時候我們可能

Spring 有一個特點,就是創建出來的 Bean 對容器是無感的,一個 Bean 是怎么樣被容器從一個 Class 整成一個 Bean 的,對于 Bean 本身來說是不知道的,當然也不需要知道,也就是 Bean 對容器的存在是無感的。ikl28資訊網——每日最新資訊28at.com

但是有時候我們可能會遇到一些場景,這些場景讓我們去感知容器的存在,松哥舉幾個例子:ikl28資訊網——每日最新資訊28at.com

  1. Spring 容器提供的功能不止 IoC、AOP 這些,常見的 I18N 也是 Spring 的能力之一,如果我們想要在自己的 Bean 中去使用 I18N,那就得去找 Spring,這樣就感知到了 Spring 容器的存在了。
  2. Spring 提供了資源加載器,如果我們想要使用這個資源加載器去加載配置,那就得去找 Spring 要,這樣就感知到了 Spring 容器的存在了。
  3. 想根據 beanName 去 Spring 容器中查找 Bean,那不用多說,肯定得知道 Spring 容器的存在。
  4. ...

也就是說,雖然 Spring 中的 Bean 可以不用去感知 Spring 容器的存在,但是在實際開發中,我們往往還是需要 Spring 容器提供的各種能力,這樣就迫使我們的 Bean 不得不去感知到 Spring 容器的存在。ikl28資訊網——每日最新資訊28at.com

那么 Spring 中的 Bean 如何感知到 Spring 容器的存在呢?ikl28資訊網——每日最新資訊28at.com

1. Aware

Aware 本身就有感知的意思。ikl28資訊網——每日最新資訊28at.com

Spring Aware 是 Spring 框架中的一個特性,它允許我們的應用程序或組件與 Spring 容器進行交互。當一個類實現了 Spring Aware 接口并注冊到 Spring 容器中時,該類就能夠感知到 Spring 容器的存在,并且可以獲取容器的一些資源或進行一些特定的操作。ikl28資訊網——每日最新資訊28at.com

Spring Aware 接口包括了多個子接口,每個子接口對應于不同的 Spring 容器資源或功能。ikl28資訊網——每日最新資訊28at.com

Aware 的實現有很多,大的方向來說主要有如下一些:ikl28資訊網——每日最新資訊28at.com

圖片圖片ikl28資訊網——每日最新資訊28at.com

每一個 Aware 的作用如下:ikl28資訊網——每日最新資訊28at.com

  • ApplicationEventPublisherAware:實現該接口的對象可以獲取事件發布的能力。
  • ServletContextAware:實現該接口的對象可以獲取到 ServletContext 對象。
  • MessageSourceAware:實現該接口的對象可以獲取到 MessageSource 對象,MessageSource 支持多消息源,主要用于主要用于國際化。
  • ResourceLoaderAware:實現該接口的對象可以獲取到一個 ResourceLoader,Spring ResourceLoader 則為我們提供了一個統一的 getResource() 方法來通過資源路徑檢索外部資源,例如文本文件、XML 文件、屬性文件或圖像文件等。
  • ApplicationStartupAware:實現該接口的對象可以獲取到一個 ApplicationStartup 對象,這個比較新,是 Spring 5.3 中新推出的,通過 ApplicationStartup 可以標記應用程序啟動期間的步驟,并收集有關執行上下文或其處理時間的數據。
  • NotificationPublisherAware:實現該接的對象可以獲取到一個 NotificationPublisher 對象,通過該對象可以實現通知的發送。
  • EnvironmentAware:實現該接口的對象可以獲取到一個 Environment 對象,通過 Environment 可以獲取到容器的環境信息。
  • BeanFactoryAware:實現該接口的對象可以獲取到一個 BeanFactory 對象,通過 BeanFactory 可以完成 Bean 的查詢等操作。
  • ImportAware:實現該接口的對象可以獲取到一個 AnnotationMetadata 對象,ImportAware 接口是需要和 @Import 注解一起使用的。在 @Import 作為元注解使用時,通過 @Import 導入的配置類如果實現了 ImportAware 接口就可以獲取到導入該配置類接口的數據配置。
  • EmbeddedValueResolverAware:實現該接口的對象可以獲取到一個 StringValueResolver 對象,通過 StringValueResolver 對象,可以讀取到 Spring 容器中的 properties 配置的值(YAML 配置也可以)。
  • ServletConfigAware:實現該接口的對象可以獲取到一個 ServletConfig 對象,不過這個似乎沒什么用,我們很少自己去配置 ServletConfig。
  • LoadTimeWeaverAware:實現該接口的對象可以獲取到一個 LoadTimeWeaver 對象,通過該對象可以獲取加載 Spring Bean 時織入的第三方模塊,如 AspectJ 等。
  • BeanClassLoaderAware:實現該接口的對象可以獲取到一個 ClassLoader 對象,ClassLoader 能干嘛不需要我多說了吧。
  • BeanNameAware:實現該接口的對象可以獲取到一個當前 Bean 的名稱。
  • ApplicationContextAware:實現該接口的對象可以獲取到一個 ApplicationContext 對象,通過 ApplicationContext 可以獲取容器中的 Bean、環境等信息。

通過實現這些接口,我們可以在應用程序中獲取 Spring 容器提供的各種資源,并與容器進行交互,以實現更靈活和可擴展的功能。ikl28資訊網——每日最新資訊28at.com

2. 實踐

舉兩個例子小伙伴們來感受下 Aware 的具體用法。ikl28資訊網——每日最新資訊28at.com

2.1 案例

例如我想在 Bean 中感知到當前 Bean 的名字,那么我們可以按照如下方式來使用:ikl28資訊網——每日最新資訊28at.com

@Servicepublic class UserService implements BeanNameAware {    private String beanName;    @Override    public void setBeanName(String name) {        this.beanName = name;    }    @Override    public String toString() {        return "UserService{" +                "beanName='" + beanName + '/'' +                '}';    }}

讓當前 bean 實現 BeanNameAware 接口,并重寫 setBeanName 方法,這個方法會在 Spring 容器初始化 Bean 的時候自動被調用,我們就可以據此獲取到 bean 的名稱了。ikl28資訊網——每日最新資訊28at.com

再比如我想做一個工具 Bean,用來查找其他 Bean,那么我可以使用如下方式:ikl28資訊網——每日最新資訊28at.com

@Componentpublic class BeanUtils implements BeanFactoryAware {    private static BeanFactory beanFactory;    @Override    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {        this.beanFactory = beanFactory;    }    public static  <T> T getBean(Class<T> clazz) {        return (T) beanFactory.getBean(clazz);    }}

讓當前 Bean 實現 BeanFactoryAware 接口并重寫 setBeanFactory 方法,在系統初始化當前 Bean 的時候,會自動調用 setBeanFactory 方法,進而將 beanFactory 變量傳進來。ikl28資訊網——每日最新資訊28at.com

2.2 原理

當 Spring 容器創建一個 Bean 的時候,大致的流程是創建實例對象 -> 屬性填充 -> Bean 初始化ikl28資訊網——每日最新資訊28at.com

最后這個 Bean 的初始化,就是調用 init 方法、afterPropertiesSet 方法以及 BeanPostProcessor 中的方法的,如下:ikl28資訊網——每日最新資訊28at.com

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { invokeAwareMethods(beanName, bean); Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) {  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try {  invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) {  throw new BeanCreationException(    (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex); } if (mbd == null || !mbd.isSynthetic()) {  wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean;}

在這個方法一進來,首先有一個 invokeAwareMethods,這個就是用來觸發 Aware 的,來看下:ikl28資訊網——每日最新資訊28at.com

private void invokeAwareMethods(String beanName, Object bean) { if (bean instanceof Aware) {  if (bean instanceof BeanNameAware beanNameAware) {   beanNameAware.setBeanName(beanName);  }  if (bean instanceof BeanClassLoaderAware beanClassLoaderAware) {   ClassLoader bcl = getBeanClassLoader();   if (bcl != null) {    beanClassLoaderAware.setBeanClassLoader(bcl);   }  }  if (bean instanceof BeanFactoryAware beanFactoryAware) {   beanFactoryAware.setBeanFactory(AbstractAutowireCapableBeanFactory.this);  } }}

小伙伴們可以看到,BeanNameAware、BeanClassLoaderAware 以及 BeanFactoryAware 這三種類型的 Aware 是在這里觸發的。ikl28資訊網——每日最新資訊28at.com

每種 Aware 因為功能不同,因此作用的時機也不同。ikl28資訊網——每日最新資訊28at.com

invokeAwareMethods 方法執行完畢之后,接下來是執行 applyBeanPostProcessorsBeforeInitialization 方法,這個我們之前分析過,這個方法最終會觸發 BeanPostProcessor#postProcessBeforeInitialization 方法的執行,而 BeanPostProcessor 有一個子類專門處理 Aware 的,就是 ApplicationContextAwareProcessor:ikl28資訊網——每日最新資訊28at.com

@Override@Nullablepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||   bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||   bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||   bean instanceof ApplicationStartupAware)) {  return bean; } invokeAwareInterfaces(bean); return bean;}private void invokeAwareInterfaces(Object bean) { if (bean instanceof Aware) {  if (bean instanceof EnvironmentAware environmentAware) {   environmentAware.setEnvironment(this.applicationContext.getEnvironment());  }  if (bean instanceof EmbeddedValueResolverAware embeddedValueResolverAware) {   embeddedValueResolverAware.setEmbeddedValueResolver(this.embeddedValueResolver);  }  if (bean instanceof ResourceLoaderAware resourceLoaderAware) {   resourceLoaderAware.setResourceLoader(this.applicationContext);  }  if (bean instanceof ApplicationEventPublisherAware applicationEventPublisherAware) {   applicationEventPublisherAware.setApplicationEventPublisher(this.applicationContext);  }  if (bean instanceof MessageSourceAware messageSourceAware) {   messageSourceAware.setMessageSource(this.applicationContext);  }  if (bean instanceof ApplicationStartupAware applicationStartupAware) {   applicationStartupAware.setApplicationStartup(this.applicationContext.getApplicationStartup());  }  if (bean instanceof ApplicationContextAware applicationContextAware) {   applicationContextAware.setApplicationContext(this.applicationContext);  } }}

大家看下,這七種類型的 Aware 是在這里被觸發的。ikl28資訊網——每日最新資訊28at.com

另外像 ImportAware 是在 ImportAwareBeanPostProcessor#postProcessBeforeInitialization 方法中處理的;LoadTimeWeaverAware 是在 、LoadTimeWeaverAwareProcessor#postProcessBeforeInitialization 方法中處理的。ikl28資訊網——每日最新資訊28at.com

基本上,大部分的 Aware 接口都是在 BeanPostProcessor 中處理的。ikl28資訊網——每日最新資訊28at.com

ikl28資訊網——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-16740-0.html如何讓 Bean 深度感知 Spring 容器

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 用 Java 深入研究樹,你了解多少?

下一篇: 如何在C#客戶端程序中無縫集成Python算法

標簽:
  • 熱門焦點
  • 盧偉冰長文解析K60至尊版 對Redmi有著里程碑式的意義

    在今天的Redmi后性能時代戰略發布會結束之后,Redmi總經理盧偉冰又帶來了一篇長文,詳解了為什么 Redmi 要開啟后性能時代?為什么選擇和 MediaTek、Pixelworks 深度合作?以及后性
  • 7月安卓手機性能榜:紅魔8S Pro再奪榜首

    7月份的手機市場風平浪靜,除了紅魔和努比亞帶來了兩款搭載驍龍8Gen2領先版處理器的新機之外,別的也想不到有什么新品了,這也正常,通常6月7月都是手機廠商修整的時間,進入8月份之
  • Golang 中的 io 包詳解:組合接口

    io.ReadWriter// ReadWriter is the interface that groups the basic Read and Write methods.type ReadWriter interface { Reader Writer}是對Reader和Writer接口的組合,
  • 從 Pulsar Client 的原理到它的監控面板

    背景前段時間業務團隊偶爾會碰到一些 Pulsar 使用的問題,比如消息阻塞不消費了、生產者消息發送緩慢等各種問題。雖然我們有個監控頁面可以根據 topic 維度查看他的發送狀態,
  • 三言兩語說透柯里化和反柯里化

    JavaScript中的柯里化(Currying)和反柯里化(Uncurrying)是兩種很有用的技術,可以幫助我們寫出更加優雅、泛用的函數。本文將首先介紹柯里化和反柯里化的概念、實現原理和應用
  • 重估百度丨“晚熟”的百度云,能等到春天嗎?

    &copy;自象限原創作者|程心排版|王喻可2016年7月13日,百度云計算戰略發布會在北京舉行,宣告著百度智能云的正式啟程。彼時的會場座無虛席,甚至排隊排到了門外,在場的所有人幾乎都
  • 阿里大調整

    來源:產品劉有媒體報道稱,近期淘寶天貓集團啟動了近年來最大的人力制度改革,涉及員工績效、層級體系等多個核心事項,目前已形成一個初步的&ldquo;征求意見版&rdquo;:1、取消P序列
  • 英特爾Xe-HP項目終止,將專注Xe-HPC/HPG系列顯卡

    據10 月 31 日消息報道,英特爾高級副總裁兼加速計算系統和圖形事業部總經理 表示,Xe-HP“ Arctic Sound” 系列服務器 GPU 已經應用于 oneAPI devcloud 云服
  • 由于成本持續增加,筆記本產品價格預計將明顯上漲

    根據知情人士透露,由于材料、物流等成本持續增加,筆記本產品價格預計將在2021年下半年有明顯上漲。進入6月下旬以來,全球半導體芯片缺貨情況加劇,顯卡、處理器
Top