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

Spring實現(xiàn)IoC和DI的方法詳解

 更新時間:2024年08月05日 09:25:53   作者:luming.02  
IoC全稱Inversion of Control (控制反轉) ,這里的控制其實是控制權的意思,可以理解為對象的獲取權力和方式發(fā)生了發(fā)轉,DI依賴注?是?個過程,是指IoC容器在創(chuàng)建Bean時, 去提供運?時所依賴的資源,?資源指的就是對象,本文介紹了Spring實現(xiàn)IoC和DI的方法

一.Spring中的IoC

IoC全稱Inversion of Control (控制反轉) ,這里的控制其實是控制權的意思。可以理解為對象的獲取權力和方式發(fā)生了發(fā)轉。也就是說,當需要某個對象時,傳統(tǒng)開發(fā)模式中需要??通過 new 創(chuàng)建對象;而IoC的思想則不一樣,IoC旨在把創(chuàng)建對象的任務交給外部的容器,程序中只需要引入容器里存放的需要的對象即可。這個容器一般被稱為:IoC容器。

其實IoC我們在前?已經(jīng)使?了,我們在前?講到,在類上?添加 @RestController 和 @Controller 注解,就是把這個對象交給Spring管理,Spring 框架啟動時就會加載該類,把對象交給Spring管理,這就是Spring中的IoC思想。Spring對于IoC的實現(xiàn)主要是通過工廠設計模式+反射來實現(xiàn)的,當我們需要某個對象的時候,只需要將創(chuàng)建對象的任務交給容器,在程序中只需要調用(注入)即可。

前?我們提到IoC控制反轉,就是將對象的控制權交給Spring的IOC容器,由IOC容器創(chuàng)建及管理對象。那么在Spring程序中,我們該如何通過代碼來實現(xiàn)IoC呢?

Spring框架為了更好的服務應用程序,提供了倆類注解來實現(xiàn)將對象集中管理創(chuàng)建:

  • 類注解:@Controller、@Service、@Repository、@Component、@Configuration
  • 方法注解:@Bean

@Controller

使? @Controller 存儲 bean 的代碼如下所?:

@Controller // 將對象存儲到 Spring 中
public class UserController {
    public void sayHi(){
        System.out.println("hi,UserController...");
    }
}

如何觀察這個對象已經(jīng)存在Spring容器當中了呢? 我們可以通過啟動類中的getBean方法來得到Spring中管理的Bean。

@SpringBootApplication
public class IoCdemoApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(IoCdemoApplication.class, args);
        UserController bean = context.getBean(UserController.class);
        bean.sayHi();
    }
}

在控制臺即可觀察到輸出:

但是一旦將@Controller注釋掉,程序就會報錯找不到這個Bean,這就說明了使用@Controller確實是可以將該類對象交給Spring進行管理

@Service

@Service
public class UserService {
    public void sayHi(String name) {
        System.out.println("Hi," + name);
    }
}

 還是來獲取一下這個對象,看看結果如何

ConfigurableApplicationContext context = SpringApplication.run(IoCdemoApplication.class, args);
UserService bean = context.getBean(UserService.class);
bean.sayHi("CSDN");

如果注釋掉@Service就會報錯,因此可以證實@Service可以將類對象交給Spring進行管理

后續(xù)的三個注解如果進行相同方式的驗證都會得到一樣的結果,這里就不再贅述 

@Repository

@Repository
public class UserRepository {
    public void sayHi() {
        System.out.println("Hi, UserRepository~");
    }
}

@Component

@Component
public class UserComponent {
    public void sayHi() {
        System.out.println("Hi, UserComponent~");
    }
}

@Configuration

@Configuration
public class UserConfiguration {
    public void sayHi() {
        System.out.println("Hi,UserConfiguration~");
    }
}

那么既然這么多注解干的都是同一件事,為什么還非要分出這么多注解呢?

類注解之間的區(qū)別

這個也是和咱們前?講的應?分層是呼應的,不同的注解標識著不同的信息,這些注解可以讓程序員看到類注解之后,就能直接了解當前類的?途。

  • @Controller:控制層, 接收請求, 對請求進?處理, 并進?響應
  • @Servie:業(yè)務邏輯層, 處理具體的業(yè)務邏輯
  • @Repository:數(shù)據(jù)訪問層,也稱為持久層. 負責數(shù)據(jù)訪問操作
  • @Configuration:配置層. 處理項?中的?些配置信息

這和每個省/市都有??的?牌號是?樣的。?牌號都是唯?的,標識?個?輛的。但是為什么還需要設置不同的?牌開頭呢??如陜西的?牌號就是:陜X:XXXXXX,北京的?牌號:京X:XXXXXX,甚??個省不同的縣區(qū)也是不同的,?如西安就是,陜A:XXXXX,咸陽:陜B:XXXXXX,寶雞,陜C:XXXXXX,?樣。

這樣做的好處除了可以節(jié)約號碼之外,更重要的作?是可以直觀的標識?輛?的歸屬地.

對于一般的開發(fā)我們通過不同的注解去確認它是哪一層的代碼,這樣更方面上下層進行調用

類注解之間的聯(lián)系

細心的朋友可能發(fā)現(xiàn)了,上述的注解中少了一個@Component注解,我們不妨打開每個注解的源碼看看。


我們會發(fā)現(xiàn)上述4個注解中都有@Component注解,這說明它們本?就是屬于 @Component 的 "?類"。@Component 是?個元注解,也就是說可以注解其他類注解,如 @Controller、@Service 、@Repository 等, 這些注解被稱為 @Component 的衍?注解。

@Controller、@Service 和 @Repository ?于更具體的?例(分別在控制層, 業(yè)務邏輯層, 持久化層),在開發(fā)過程中,如果你要在業(yè)務邏輯層使? @Component 或 @Service,顯然@Service是更好的選擇。

諸如@Configuration,見名知意就是用來標記配置相關的,比如我們想用Redis的數(shù)據(jù)庫,在使用Redis之前需要對Redis數(shù)據(jù)庫的密碼或者庫做一些配置,配置好了之后我們需要將這個配置類交給Spring管理方便我們在別的地方直接訪問Redis數(shù)據(jù)庫,這時使用@Configuration就是很好的選擇。

?如杯?有喝?杯、刷?杯等,但是我們更傾向于在?常喝?時使??杯,洗漱時使?刷?杯。

方法注解@Bean

類注解是添加到某個類上的, 但是存在兩個問題

  • 使?外部包?的類, 沒辦法添加類注解
  • ?個類, 需要多個對象, ?如多個數(shù)據(jù)源

比如我們想通過引入第三方的工具類去操作數(shù)據(jù)庫,我們想將這個類交給Spring管理方便我們進行二次開發(fā),但是由于第三方包只能讀取不能寫入的情況,就會陷入進退倆難的情況。

@Bean 同上述類注解的功能一樣,都是將標記的對象交給Spring進行管理,但在 Spring 框架的設計中,?法注解 @Bean 要配合類注解才能將對象正常的存儲到 Spring 容器中,如下代碼所?:

@Component
public class BeanConfig {
    @Bean
    public User user(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
}

我們也可以通過設置name屬性給Bean對象進行重命名

@Bean(name = {"u1","user1"})

二.DI——Dependency Injection(依賴注入)

依賴注?是?個過程,是指IoC容器在創(chuàng)建Bean時, 去提供運?時所依賴的資源,?資源指的就是對象,在之前程序案例中,我們使?了 @Autowired 這個注解,完成了依賴注?的操作。

關于依賴注?,Spring也給我們提供了三種?式:

  • 屬性注?(Field Injection)
  • 構造?法注?(Constructor Injection)
  • Setter 注?(Setter Injection)

屬性注入

屬性注?是使? @Autowired 實現(xiàn)的,將 Service 類注?到 Controller 類中。

Service 類的實現(xiàn)代碼如下:

import org.springframework.stereotype.Service;
 
@Service
public class UserService {
    public void sayHi() {
        System.out.println("Hi,UserService");
    }
}

Controller 類的實現(xiàn)代碼如下: 

@Controller
public class UserController {
    //注??法1: 屬性注?
    @Autowired
    private UserService userService;
    
    public void sayHi() {
        System.out.println("hi,UserController...");
        userService.sayHi();
    }
}

構造方法注入

構造?法注?是在類的構造?法中實現(xiàn)注?,如下代碼所?:

@Controller
public class UserController2 {
    //注??法2: 構造?法
    private UserService userService;
    @Autowired
    public UserController2(UserService userService) {
        this.userService = userService;
    }
    public void sayHi(){
        System.out.println("hi,UserController2...");
        userService.sayHi();
    }
}

如果類只有?個構造?法,那么 @Autowired 注解可以省略;如果類中有多個構造?法,那么需要添加上 @Autowired 來明確指定到底使?哪個構造?法。

Setter注入

Setter 注?和屬性的 Setter ?法實現(xiàn)類似,只不過在設置 set ?法的時候需要加上 @Autowired 注解 ,如下代碼所?:

@Controller
public class UserController3 {
    //注??法3: Setter?法注?
    private UserService userService;
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    public void sayHi(){
        System.out.println("hi,UserController3...");
        userService.sayHi();
    }
}

三種注入的優(yōu)缺點

屬性注?

優(yōu)點:

  • 簡潔,使??便

缺點:

  • 只能?于 IoC 容器,如果是? IoC 容器不可?,并且只有在使?的時候才會出現(xiàn) NPE(空指針異常)
  • 不能注??個Final修飾的屬性

構造函數(shù)注入(Spring 4.X推薦)

優(yōu)點:

  • 可以注?final修飾的屬性
  • 注?的對象不會被修改
  • 依賴對象在使?前?定會被完全初始化,因為依賴是在類的構造?法中執(zhí)?的,?構造?法是在類加載階段就會執(zhí)?的?法.
  • 通?性好, 構造?法是JDK?持的, 所以更換任何框架,他都是適?的

缺點:

  • 注?多個對象時, 代碼會?較繁瑣

Setter注入(Spring 3.X推薦)

優(yōu)點:

  • ?便在類實例之后, 重新對該對象進?配置或者注?

缺點:

  • 不能注??個Final修飾的屬性
  • 注?對象可能會被改變, 因為setter?法可能會被多次調?, 就有被修改的?險

@Autowired存在問題

當同?類型存在多個bean時, 使?@Autowired會存在問題

@Component
public class BeanConfig {
    @Bean("u1")
    public User user1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
    @Bean
    public User user2() {
        User user = new User();
        user.setName("lisi");
        user.setAge(19);
        return user;
    }
}
@Controller
public class UserController {
    
    @Autowired
    private UserService userService;
    //注?user
    @Autowired
    private User user;
    public void sayHi(){
        System.out.println("hi,UserController...");
        userService.sayHi();
        System.out.println(user);
    }
}

程序會出現(xiàn)無法正確找到Bean的報錯

如何解決上述問題呢?Spring提供了以下?種解決?案:

  • @Primary
  • @Qualifier
  • @Resource

使?@Primary注解:當存在多個相同類型的Bean注?時,加上@Primary注解,來確定默認的實現(xiàn)

@Component
public class BeanConfig {
    @Primary //指定該bean為默認bean的實現(xiàn)
    @Bean("u1")
    public User user1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
    @Bean
    public User user2() {
        User user = new User();
        user.setName("lisi");
        user.setAge(19);
        return user;
    }
}

使?@Qualifier注解:指定當前要注?的bean對象。 在@Qualifier的value屬性中,指定注?的bean的名稱(@Qualifier注解不能單獨使?,必須配合@Autowired使?)

@Controller
public class UserController {
    @Qualifier("user2") //指定bean名稱
    @Autowired
    private User user;
    public void sayHi(){
        System.out.println("hi,UserController...");
        System.out.println(user);
    }
}

使?@Resource注解:是按照bean的名稱進?注?。通過name屬性指定要注?的bean的名稱。并且由于@Resource是由JDK提供的,因此在其他框架下也有可延展性。

@Controller
public class UserController {
    @Resource(name = "user2")
    private User user;
    public void sayHi(){
        System.out.println("hi,UserController...");
        System.out.println(user);
    }
}

@Autowired 是spring框架提供的注解,?@Resource是JDK提供的注解

@Autowired 默認是按照類型注?,?@Resource是按照名稱注?。相?于 @Autowired 來說 @Resource ?持更多的參數(shù)設置,例如 name 設置,根據(jù)名稱獲取 Bean

以上就是Spring實現(xiàn)IoC和DI的方法詳解的詳細內(nèi)容,更多關于Spring實現(xiàn)IoC和DI的資料請關注腳本之家其它相關文章!

相關文章

  • SpringBoot 自定義注解異步記錄復雜日志詳解

    SpringBoot 自定義注解異步記錄復雜日志詳解

    這篇文章主要為大家介紹了SpringBoot 自定義注解異步記錄復雜日志詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • Java使用Spire.Presentation for Java庫合并PowerPoint的技術教程

    Java使用Spire.Presentation for Java庫合并PowerPoint的技術教

    在現(xiàn)代企業(yè)和個人開發(fā)中,文檔處理是不可或缺的一環(huán),尤其是在報告演示、內(nèi)容整合等場景下,PowerPoint 文件的自動化處理需求日益增長,本文將深入探討如何利用 Java 編程語言,結合強大的 Spire.Presentation for Java庫,實現(xiàn)PowerPoiont文件的合并
    2026-01-01
  • java.text.DecimalFormat用法詳解

    java.text.DecimalFormat用法詳解

    這篇文章主要為大家詳細介紹了java.text.DecimalFormat用法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 詳解JAVA流程控制語句

    詳解JAVA流程控制語句

    這篇文章主要介紹了Java中的流程控制語句,循環(huán)等語句是Java編程中流程控制的基礎,需要的朋友可以參考下
    2017-04-04
  • 關于使用Mybatisplus自帶的selectById和insert方法時的一些問題

    關于使用Mybatisplus自帶的selectById和insert方法時的一些問題

    這篇文章主要介紹了關于使用Mybatisplus自帶的selectById和insert方法時的一些問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • 為Java應用創(chuàng)建Docker鏡像的3種方式總結

    為Java應用創(chuàng)建Docker鏡像的3種方式總結

    Docker的使用可以將應用程序做成鏡像,這樣可以將鏡像發(fā)布到私有或者公有倉庫中,在其他主機上也可以pull鏡像,并且運行容器,運行程,下面這篇文章主要給大家總結介紹了關于為Java應用創(chuàng)建Docker鏡像的3種方式,需要的朋友可以參考下
    2023-06-06
  • 在SpringBoot+MyBatis項目中實現(xiàn)MySQL讀寫分離的實戰(zhàn)指南

    在SpringBoot+MyBatis項目中實現(xiàn)MySQL讀寫分離的實戰(zhàn)指南

    在Spring Boot和MyBatis項目中實現(xiàn)MySQL讀寫分離,主要有兩種思路:一種是在應用層通過代碼和配置手動控制,另一種是借助中間件自動路由,本文介紹了幾種主流的實現(xiàn)方案,需要的朋友可以參考下
    2025-11-11
  • java實現(xiàn)動態(tài)驗證碼

    java實現(xiàn)動態(tài)驗證碼

    這篇文章主要為大家詳細介紹了java實現(xiàn)動態(tài)驗證碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • 分布式調度XXL-Job整合Springboot2.X實戰(zhàn)操作過程(推薦)

    分布式調度XXL-Job整合Springboot2.X實戰(zhàn)操作過程(推薦)

    這篇文章主要介紹了分布式調度XXL-Job整合Springboot2.X實戰(zhàn)操作,包括定時任務的使用場景和常見的定時任務,通過本文學習幫助大家該選擇哪個分布式任務調度平臺,對此文感興趣的朋友一起看看吧
    2022-04-04
  • Java中@Accessors注解的具體使用

    Java中@Accessors注解的具體使用

    @Accessors是Lombok提供的注解之一,用于自動生成getter和setter方法,本文主要介紹了@Accessors注解的常用屬性,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01

最新評論

博客| 始兴县| 宁都县| 昌黎县| 山东省| 那坡县| 宣城市| 栾城县| 克什克腾旗| 蓝山县| 龙川县| 根河市| 久治县| 天柱县| 台山市| 蛟河市| 留坝县| 永胜县| 临海市| 宁武县| 宜川县| 太白县| 米易县| 宜州市| 昌吉市| 黄大仙区| 边坝县| 自治县| 连城县| 迁西县| 泰兴市| 丹巴县| 万盛区| 秭归县| 安龙县| 阿拉善左旗| 锡林郭勒盟| 嵊州市| 尤溪县| 太和县| 苍梧县|