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

Spring?IOC功能詳解

 更新時(shí)間:2025年06月04日 09:38:05   作者:?abc!  
在Java開(kāi)發(fā)中,Ioc意味著將你設(shè)計(jì)好的對(duì)象交給容器控制,而不是傳統(tǒng)的在你的對(duì)象內(nèi)部直接控制,本文給大家介紹Spring?IOC的相關(guān)知識(shí),感興趣的朋友一起看看吧

概述

為什么叫控制反轉(zhuǎn)

Spring Bean是什么:Spring里面的bean就類似是定義的一個(gè)組件,而這個(gè)組件的作用就是實(shí)現(xiàn)某個(gè)功能的,這里所定義的bean就相當(dāng)于給了你一個(gè)更為簡(jiǎn)便的方法來(lái)調(diào)用這個(gè)組件去實(shí)現(xiàn)你要完成的功能

Spring框架管理這些Bean的創(chuàng)建工作,即由用戶管理Bean轉(zhuǎn)變?yōu)榭蚣芄芾鞡ean,這個(gè)就叫控制反轉(zhuǎn) - Inversion of Control (IoC)

  • 這些托管創(chuàng)建的Bean放在IoC Container
  • 為了更好讓用戶配置Bean,引入不同方式來(lái)配置Bean:xml配置,Java配置,注解配置等支持
  • Spring也管理整個(gè)Bean的生命周期
  • 應(yīng)用程序代碼從Ioc Container中獲取依賴的Bean,注入到應(yīng)用程序中,這個(gè)過(guò)程叫 依賴注入(Dependency Injection,DI)

控制反轉(zhuǎn)是通過(guò)依賴注入實(shí)現(xiàn)的,IoC是設(shè)計(jì)思想,DI是實(shí)現(xiàn)方式

IOC不是什么技術(shù),是一種設(shè)計(jì)思想

在Java開(kāi)發(fā)中,Ioc意味著將你設(shè)計(jì)好的對(duì)象交給容器控制,而不是傳統(tǒng)的在你的對(duì)象內(nèi)部直接控制

  • 正轉(zhuǎn):傳統(tǒng)應(yīng)用程序是由我們自己在對(duì)象中主動(dòng)控制去直接獲取依賴對(duì)象
  • 反轉(zhuǎn):由容器來(lái)幫忙創(chuàng)建及注入依賴對(duì)象
  • 由IoC容器幫對(duì)象找相應(yīng)的依賴對(duì)象并注入,而不是由對(duì)象主動(dòng)去找

Spring 中的 bean 的作用域

基礎(chǔ)概念

singleton : 唯一 bean 實(shí)例,Spring 中的 bean 默認(rèn)都是單例的。
prototype : 每次請(qǐng)求都會(huì)創(chuàng)建一個(gè)新的 bean 實(shí)例。

Spring并不管理作用域?yàn)閜rototype的bean的整個(gè)生命周期,使用者必須自己銷毀 這個(gè)bean并釋放資源。

下述作用域只有在web環(huán)境下才有用

  • request : 每一次 HTTP 請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的 bean,該 bean 僅在當(dāng)前 HTTP request 內(nèi)有效。
  • session : 每一次 HTTP 請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的 bean,該 bean 僅在當(dāng)前 HTTP session 內(nèi)有效
  • global-session: 全局 session 作用域,僅僅在基于 Portlet 的 web 應(yīng)用中才有意義,Spring5 已經(jīng)沒(méi)有了。
  • Portlet 是能夠生成語(yǔ)義代碼(例如:HTML)片段的小型 Java Web 插件。它們基于 portlet 容器,可以像 servlet 一樣處理 HTTP 請(qǐng)求。但是,與 servlet 不同,每個(gè) portlet 都有不同的會(huì)話

對(duì)比

作用域說(shuō)明典型應(yīng)用場(chǎng)景
singleton默認(rèn)作用域,容器內(nèi)唯一實(shí)例無(wú)狀態(tài)Service、工具類
prototype每次注入創(chuàng)建新實(shí)例有狀態(tài)Bean、含可變狀態(tài)的組件
request每個(gè)HTTP請(qǐng)求創(chuàng)建新實(shí)例Web請(qǐng)求上下文相關(guān)對(duì)象
session每個(gè)用戶會(huì)話創(chuàng)建新實(shí)例用戶購(gòu)物車、登錄信息
application整個(gè)Web應(yīng)用生命周期單例全局配置

有狀態(tài)和無(wú)狀態(tài)的bean

基本概念

在 Spring 框架中,有狀態(tài) Bean 和 無(wú)狀態(tài) Bean 是兩種重要的對(duì)象設(shè)計(jì)模式,它們的核心區(qū)別在于 是否保存可變狀態(tài),直接影響線程安全性和作用域管理

有狀態(tài) Bean 注意事項(xiàng)

  • 作用域控制:必須顯式聲明作用域(如 @Scope(“prototype”))。
  • 避免單例陷阱:禁止在單例 Bean 中注入有狀態(tài) Bean(除非使用 ThreadLocal)。
  • 防御性編程:返回?cái)?shù)據(jù)時(shí)返回副本而非引用

無(wú)狀態(tài) Bean 最佳實(shí)踐

  • 方法參數(shù)化:所有數(shù)據(jù)通過(guò)方法參數(shù)傳遞。
  • 依賴注入:通過(guò)構(gòu)造函數(shù)注入其他 Bean。
  • 工具類設(shè)計(jì):將狀態(tài)抽取到參數(shù)中

建議

  • 優(yōu)先無(wú)狀態(tài)設(shè)計(jì):90%的業(yè)務(wù)場(chǎng)景應(yīng)使用無(wú)狀態(tài)Bean
  • 有狀態(tài)Bean最小化:必須使用時(shí)有明確的作用域控制
  • 避免混合狀態(tài):不要在同一Bean中混用有狀態(tài)和無(wú)狀態(tài)代碼

對(duì)比

特征有狀態(tài) Bean無(wú)狀態(tài) Bean
實(shí)例變量/狀態(tài)存儲(chǔ)包含可變的成員變量(會(huì)隨操作改變)無(wú)成員變量,或只有不可變常量
線程安全需自行保證線程安全(如加鎖、隔離)天然線程安全(無(wú)共享狀態(tài))
作用域通常用 prototype 作用域(每次注入新實(shí)例)通常用 singleton 作用域(全局共享)
復(fù)用性不同請(qǐng)求需不同實(shí)例(需頻繁創(chuàng)建實(shí)例)、資源消耗較高全局共享單個(gè)實(shí)例、高性能(單例復(fù)用)
典型場(chǎng)景用戶會(huì)話、購(gòu)物車、事務(wù)上下文工具類、Service層業(yè)務(wù)邏輯

Ioc 配置的三種方式

總體上目前的主流方式是: 注解 + Java 配置

xml 配置

將bean的信息配置.xml文件里,通過(guò)Spring加載文件為我們創(chuàng)建bean。

  • 優(yōu)點(diǎn): 可以使用于任何場(chǎng)景,結(jié)構(gòu)清晰,通俗易懂
  • 缺點(diǎn): 配置繁瑣,不易維護(hù),枯燥無(wú)味,擴(kuò)展性差
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- services -->
    <bean id="userService" class="com.service.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>
    <!-- more bean definitions for services go here -->
</beans>

Java 配置

將類的創(chuàng)建交給我們配置的JavcConfig類來(lái)完成,Spring只負(fù)責(zé)維護(hù)和管理,采用純Java創(chuàng)建方式。其本質(zhì)上就是把在XML上的配置聲明轉(zhuǎn)移到Java配置類中

  • 優(yōu)點(diǎn):適用于任何場(chǎng)景,配置方便,因?yàn)槭羌僇ava代碼,擴(kuò)展性高,十分靈活
  • 缺點(diǎn):由于是采用Java類的方式,聲明不明顯,如果大量配置,可讀性比較差
@Configuration
public class BeansConfig {
    /**
     * @return user dao
     */
    @Bean("userDao")
    public UserDaoImpl userDao() {
        return new UserDaoImpl();
    }
    /**
     * @return user service
     */
    @Bean("userService")
    public UserServiceImpl userService() {
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(userDao());
        return userService;
    }
}

注解配置

通過(guò)在類上加注解的方式,來(lái)聲明一個(gè)類交給Spring管理,Spring會(huì)自動(dòng)掃描帶有@Component,@Controller,@Service,@Repository這四個(gè)注解的類,然后幫我們創(chuàng)建并管理,前提是需要先配置Spring的注解掃描器。

  • 優(yōu)點(diǎn):開(kāi)發(fā)便捷,通俗易懂,方便維護(hù)。
  • 缺點(diǎn):具有局限性,對(duì)于一些第三方資源,無(wú)法添加注解。只能采用XML或JavaConfig的方式配置

依賴注入的三種方式

常用的注入方式主要有三種:構(gòu)造方法注入(Construct注入),setter注入,基于注解的注入(接口注入)

setter方式

通過(guò)對(duì)應(yīng)變量的setXXX()方法以及在方法上面使用注解,來(lái)完成依賴注入。
Setter方法注入是通過(guò)在類中提供setter方法來(lái)注入依賴項(xiàng)的。Spring容器會(huì)調(diào)用這些setter方法來(lái)設(shè)置依賴項(xiàng)的值。這種方式更加靈活,因?yàn)榭梢栽趯?duì)象創(chuàng)建后的任何時(shí)候注入依賴項(xiàng)。

比如:在 Spring 4.3 及以后的版本中,setter 上面的 @Autowired 注解是可以不寫(xiě)的。

private Helper helper;
@Autowired
public void setHelper(Helper helper) {
    this.helper = helper;
}

優(yōu)點(diǎn):

  • 可以在對(duì)象創(chuàng)建后的任何時(shí)候注入依賴項(xiàng)。
  • 可以重新配置已存在的對(duì)象。

缺點(diǎn):

  • 可能導(dǎo)致對(duì)象狀態(tài)的不確定性,因?yàn)橐蕾図?xiàng)可以在任何時(shí)候被更改。
  • 不支持不可變對(duì)象。

構(gòu)造方法注入

將各個(gè)必需的依賴全部放在帶有注解構(gòu)造方法的參數(shù)中,并在構(gòu)造方法中完成對(duì)應(yīng)變量的初始化,這種方式,就是基于構(gòu)造方法的注入。
比如:在 Spring 4.3 及以后的版本中,如果這個(gè)類只有一個(gè)構(gòu)造方法,那么這個(gè)構(gòu)造方法上面也可以不寫(xiě) @Autowired 注解。

private final Svc svc;
@Autowired
public HelpService(@Qualifier("svcB") Svc svc) {
    this.svc = svc;
}

優(yōu)點(diǎn):

  • 確保依賴項(xiàng)在對(duì)象創(chuàng)建時(shí)就被初始化。
  • 可以設(shè)置依賴項(xiàng)為final,確保它們不會(huì)被修改。
  • 支持不可變對(duì)象。

缺點(diǎn):

  • 如果類有很多依賴項(xiàng),構(gòu)造函數(shù)可能會(huì)變得很長(zhǎng)且難以閱讀

基于注解(字段)的注入

示例

public class MyService {
    @Autowired
    private MyRepository repository;
}

優(yōu)點(diǎn):

  • 代碼簡(jiǎn)單明了,易于實(shí)現(xiàn)。

缺點(diǎn):根據(jù)Spring官方的建議,推薦使用構(gòu)造器注入和Setter注入,而盡量避免使用字段注入。字段注入被認(rèn)為是一種不太理想的方式,因?yàn)樗哂幸韵氯秉c(diǎn):

  • 不利于不變性:與構(gòu)造器注入不同,字段注入無(wú)法將不變的依賴關(guān)系傳遞給組件,因?yàn)樽侄慰梢栽谌魏螘r(shí)候更改。
  • 可見(jiàn)性問(wèn)題:外部無(wú)法明確看到組件所依賴的內(nèi)容,因?yàn)橐蕾囮P(guān)系被隱藏在組件內(nèi)部。這可能導(dǎo)致代碼可讀性下降。
  • 緊密綁定:字段注入會(huì)導(dǎo)致組件與IoC容器緊密綁定,使組件在沒(méi)有容器的情況下難以使用,也使單元測(cè)試更加復(fù)雜。
  • 不明顯的依賴關(guān)系:當(dāng)依賴關(guān)系變得復(fù)雜時(shí),使用字段注入可能導(dǎo)致依賴關(guān)系不夠明顯,難以理解組件的需求。

推薦@Resource而不是@Autowired注解

  • @Resource具有更廣泛的兼容性
    • @Autowired是Spring特定的注解,與Spring框架緊密相關(guān)。如果以后決定更換不同的IoC容器,那么@Autowired可能不再適用,因?yàn)槠渌萜骺赡懿恢С炙?/li>
    • @Resource是Java標(biāo)準(zhǔn)(JSR-250)提供的注解,幾乎所有的IoC容器都會(huì)支持它。因此,即使你將來(lái)更換了容器,使用@Resource的代碼仍然可以正常工作,不需要類似的警告。
  • 提高了代碼的可移植性:認(rèn)為@Resource更符合Java的標(biāo)準(zhǔn)化。

IOC設(shè)計(jì)體系

流程圖

IOC初始化流程

  • 初始化的入口在容器實(shí)現(xiàn)中的 refresh()調(diào)用來(lái)完成
  • 對(duì) bean 定義載入 IOC 容器使用的方法是 loadBeanDefinition,其中的大致過(guò)程如下:
    • 通過(guò) ResourceLoader 來(lái)完成資源文件位置的定位,bean 定義文件時(shí)通過(guò)抽象成 Resource 來(lái)被 IOC 容器處理的
    • 通過(guò) BeanDefinitionReader來(lái)完成定義信息的解析和 Bean 信息的注冊(cè)
    • 容器解析得到 BeanDefinition 以后,需要把它在 IOC 容器中注冊(cè),這由 IOC 實(shí)現(xiàn) BeanDefinitionRegistry 接口來(lái)實(shí)現(xiàn)。
    • 注冊(cè)過(guò)程就是在 IOC 容器內(nèi)部維護(hù)的一個(gè)HashMap 來(lái)保存得到的 BeanDefinition 的過(guò)程。
    • 這個(gè) HashMap 是 IoC 容器持有 bean 信息的場(chǎng)所,以后對(duì) bean 的操作都是圍繞這個(gè)HashMap 來(lái)實(shí)現(xiàn)的.
    • 流程圖如下:

  • 然后我們就可以通過(guò) BeanFactory 和 ApplicationContext 來(lái)享受到 Spring IOC 的服務(wù)了

Bean實(shí)例化(生命周期,循環(huán)依賴等)

最終的將Bean的定義即BeanDefinition放到beanDefinitionMap中,本質(zhì)上是一個(gè)ConcurrentHashMap<String, Object>;
并且BeanDefinition接口中包含了這個(gè)類的Class信息以及是否是單例等;

解決循環(huán)依賴問(wèn)題

Spring如何解決循環(huán)依賴問(wèn)題

Spring只是解決了單例模式下屬性依賴的循環(huán)問(wèn)題:Spring為了解決單例的循環(huán)依賴問(wèn)題,使用了三級(jí)緩存。

三級(jí)緩存詳細(xì):見(jiàn)這篇

Spring為什么不能解決多例的循環(huán)依賴:多實(shí)例Bean是每次調(diào)用一次getBean都會(huì)執(zhí)行一次構(gòu)造方法并且給屬性賦值,根本沒(méi)有三級(jí)緩存,因此不能解決循環(huán)依賴

  • 這類循環(huán)依賴問(wèn)題可以通過(guò)把bean改成單例的解決。

Spring為什么不能解決prototype作用域循環(huán)依賴:spring不會(huì)緩存prototype作用域的bean,而spring中循環(huán)依賴的解決正是通過(guò)緩存來(lái)實(shí)現(xiàn)的。

  • 這類循環(huán)依賴問(wèn)題可以通過(guò)使用@Lazy注解解決。 生成代理對(duì)象產(chǎn)生的循環(huán)依賴

生成代理對(duì)象產(chǎn)生的循環(huán)依賴,解決方法很多,主要有:

  • 使用@Lazy注解,延遲加載
  • 使用@DependsOn注解,指定加載先后關(guān)系
  • 修改文件名稱,改變循環(huán)依賴類的加載順序

使用@DependsOn產(chǎn)生的循環(huán)依賴:這類循環(huán)依賴問(wèn)題要找到@DependsOn注解循環(huán)依賴的地方,迫使它不循環(huán)依賴就可以解決問(wèn)題。

Spring中Bean的生命周期

Spring 只幫我們管理單例模式 Bean 的完整生命周期,對(duì)于 prototype 的 bean ,Spring 在創(chuàng)建好交給使用者之后則不會(huì)再管理后續(xù)的生命周期。

  • prototype 是一種 bean 的作用域。它的主要特點(diǎn)是每次請(qǐng)求都會(huì)創(chuàng)建一個(gè)新的 bean 實(shí)例
  • 與 singleton 作用域不同,singleton只會(huì)創(chuàng)建一個(gè)共享的實(shí)例。

Bean的完整生命周期經(jīng)歷了各種方法調(diào)用,這些方法可以劃分為以下幾類:(結(jié)合上圖,需要有如下頂層思維)

  • Bean自身的方法: 這個(gè)包括了Bean本身調(diào)用的方法和通過(guò)配置文件中的init-method和destroy-method指定的方法
  • Bean級(jí)生命周期接口方法: 這個(gè)包括了BeanNameAware、BeanFactoryAware、ApplicationContextAware;當(dāng)然也包括InitializingBean和DiposableBean這些接口的方法(可以被@PostConstruct和@PreDestroy注解替代)
  • 容器級(jí)生命周期接口方法: 這個(gè)包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 這兩個(gè)接口實(shí)現(xiàn),一般稱它們的實(shí)現(xiàn)類為“后處理器”。
  • 工廠后處理器接口方法: 這個(gè)包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工廠后處理器接口的方法。工廠后處理器也是容器級(jí)的。在應(yīng)用上下文裝配配置文件之后立即調(diào)用

到此這篇關(guān)于Spring IOC詳解的文章就介紹到這了,更多相關(guān)Spring IOC詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 什么是Base64以及在Java中如何使用Base64編碼

    什么是Base64以及在Java中如何使用Base64編碼

    這篇文章主要介紹了什么是Base64以及在Java中如何使用Base64編碼的相關(guān)資料,文中包括Base64編碼的基本原理、應(yīng)用、Java實(shí)現(xiàn)、URL安全編碼以及在JavaScript中的使用方法,需要的朋友可以參考下
    2024-12-12
  • java中url漢字編碼互相轉(zhuǎn)換實(shí)例

    java中url漢字編碼互相轉(zhuǎn)換實(shí)例

    這篇文章介紹了java中url漢字編碼互相轉(zhuǎn)換實(shí)例,有需要的朋友可以參考一下
    2013-10-10
  • spring boot配置druid連接池的完整步驟

    spring boot配置druid連接池的完整步驟

    這篇文章主要給大家介紹了關(guān)于spring boot配置druid連接池的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • 使用idea遠(yuǎn)程調(diào)試jar包的配置過(guò)程

    使用idea遠(yuǎn)程調(diào)試jar包的配置過(guò)程

    這篇文章主要介紹了使用idea遠(yuǎn)程調(diào)試jar包的配置過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • DTO 實(shí)現(xiàn) service 和 controller 之間值傳遞的操作

    DTO 實(shí)現(xiàn) service 和 controller 之間值傳遞的操作

    這篇文章主要介紹了DTO 實(shí)現(xiàn) service 和 controller 之間值傳遞的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • Java中接口和抽象類的區(qū)別與相同之處

    Java中接口和抽象類的區(qū)別與相同之處

    這篇文章主要介紹了Java中接口和抽象類的區(qū)別與相同之處,本文講解了抽象類的概念、接口的概念、接口和抽象類的區(qū)別與聯(lián)系等內(nèi)容,需要的朋友可以參考下
    2015-06-06
  • Java注解詳解及實(shí)現(xiàn)自定義注解的方法

    Java注解詳解及實(shí)現(xiàn)自定義注解的方法

    這篇文章主要介紹了Java注解詳解及實(shí)現(xiàn)自定義注解的方法,本文給大家介紹了jdk中預(yù)定義的一些注解及自定義注解的相關(guān)知識(shí),需要的朋友可以參考下
    2022-06-06
  • SpringMVC配置攔截器實(shí)現(xiàn)登錄控制的方法

    SpringMVC配置攔截器實(shí)現(xiàn)登錄控制的方法

    這篇文章主要介紹了SpringMVC配置攔截器實(shí)現(xiàn)登錄控制的方法,SpringMVC讀取Cookie判斷用戶是否登錄,對(duì)每一個(gè)action都要進(jìn)行判斷,有興趣的可以了解一下。
    2017-03-03
  • 淺談Java方法調(diào)用的優(yōu)先級(jí)問(wèn)題

    淺談Java方法調(diào)用的優(yōu)先級(jí)問(wèn)題

    這篇文章主要介紹了淺談Java方法調(diào)用的優(yōu)先級(jí)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • Java設(shè)計(jì)模式之備忘錄模式實(shí)現(xiàn)對(duì)象狀態(tài)的保存和恢復(fù)

    Java設(shè)計(jì)模式之備忘錄模式實(shí)現(xiàn)對(duì)象狀態(tài)的保存和恢復(fù)

    本文介紹Java設(shè)計(jì)模式之備忘錄模式,該模式可以實(shí)現(xiàn)對(duì)象狀態(tài)的保存和恢復(fù)。通過(guò)詳細(xì)講解備忘錄模式的原理、實(shí)現(xiàn)方法和應(yīng)用場(chǎng)景,幫助讀者深入理解該設(shè)計(jì)模式,并提供示例代碼和技巧,便于讀者實(shí)際應(yīng)用
    2023-04-04

最新評(píng)論

云梦县| 揭西县| 玛曲县| 宣城市| 自治县| 昭平县| 福清市| 酒泉市| 天水市| 女性| 深州市| 平安县| 房产| 仁怀市| 红桥区| 得荣县| 东阳市| 大余县| 阿合奇县| 四川省| 焉耆| 呈贡县| 张家口市| 抚远县| 盘锦市| 湛江市| 和田县| 沭阳县| 和顺县| 城步| 山阴县| 井陉县| 怀安县| 融水| 宜良县| 临武县| 泾阳县| 澄迈县| 新建县| 蛟河市| 皋兰县|