亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring IoC 容器的使用詳解(最新整理)

 更新時(shí)間:2025年07月02日 15:16:24   作者:2的n次方_  
文章介紹了Spring框架中的應(yīng)用分層思想與IoC容器原理,通過(guò)分層解耦業(yè)務(wù)邏輯、數(shù)據(jù)訪(fǎng)問(wèn)等模塊,IoC容器利用@Component注解管理Bean,實(shí)現(xiàn)依賴(lài)注入與動(dòng)態(tài)獲取,本文給大家介紹Spring IoC 容器的使用詳解,感興趣的朋友一起看看吧

1. 應(yīng)用分層

應(yīng)用分層是一種軟件開(kāi)發(fā)設(shè)計(jì)思想,它將應(yīng)用程序分成 N 個(gè)層次,這 N 個(gè)層次分別負(fù)責(zé)各自的職責(zé),多個(gè)層次之間協(xié)同提供完整的功能,根據(jù)項(xiàng)目的復(fù)雜度,可以分成三層,四層或更多層,MVC 就是把整體的程序分成了 Model(模型), View(視圖), Controller(控制器)三個(gè)層次

由于后端開(kāi)發(fā),不需要過(guò)多的關(guān)注前端,所以又有了一種分層架構(gòu):把整體架構(gòu)分為表現(xiàn)層,業(yè)務(wù)邏輯層,數(shù)據(jù)層,又稱(chēng)為“三層架構(gòu)”

  1. 表現(xiàn)層:用來(lái)展示數(shù)據(jù)結(jié)果和接收用戶(hù)指令,是最接近用戶(hù)的一層
  2. 業(yè)務(wù)邏輯層:負(fù)責(zé)處理業(yè)務(wù)邏輯,包含業(yè)務(wù)邏輯的具體實(shí)現(xiàn)
  3. 數(shù)據(jù)層:負(fù)責(zé)存儲(chǔ)和管理與應(yīng)用程序相關(guān)的數(shù)據(jù)

在 Spring 的實(shí)現(xiàn)中可以分為下面三個(gè)部分:

Controller:控制層。接收前端發(fā)送的請(qǐng)求,對(duì)請(qǐng)求進(jìn)行處理,并響應(yīng)數(shù)據(jù)

Service:業(yè)務(wù)邏輯層。處理具體的業(yè)務(wù)邏輯

Dao:數(shù)據(jù)訪(fǎng)問(wèn)層,也被稱(chēng)為持久層。負(fù)責(zé)數(shù)據(jù)訪(fǎng)問(wèn),操作(增刪查改)

2. IoC 的介紹

IoC:也就是控制反轉(zhuǎn)

Spring IoC 是一種設(shè)計(jì)模式,用于解耦對(duì)象之間的依賴(lài)關(guān)系,在之前創(chuàng)建的項(xiàng)目中對(duì)象通常會(huì)主動(dòng)創(chuàng)建和管理自己所依賴(lài)的對(duì)象,例如,一個(gè)UserService類(lèi)可能會(huì)在自己的內(nèi)部使用new關(guān)鍵字來(lái)創(chuàng)建一個(gè)UserRepository對(duì)象用于數(shù)據(jù)訪(fǎng)問(wèn),這樣設(shè)計(jì)看似沒(méi)有問(wèn)題,但是可維護(hù)性卻很低,當(dāng)有很多類(lèi)創(chuàng)建了各自的對(duì)象時(shí),并且這些對(duì)象之間還有依賴(lài)關(guān)系,例如創(chuàng)建 Car ,F(xiàn)ramework,Bottom,Tire 類(lèi),從左到右依次存在依賴(lài)關(guān)系,當(dāng)其中有一個(gè)類(lèi)的底層代碼改變之后,調(diào)用鏈上的代碼都需要修改

public class NewCarExample {
    public static void main(String[] args) {
        Car car = new Car(20);
        car.run();
    }
    //Car類(lèi)
    static class Car {
        private Framework framework;
        public Car(int size) {
            framework = new Framework(size);
            System.out.println("Car init....");
        }
        public void run(){
            System.out.println("Car run...");
        }
    }
    //車(chē)身類(lèi)
    static class Framework {
        private Bottom bottom;
        public Framework(int size) {
            bottom = new Bottom(size);
            System.out.println("Framework init...");
        }
    }
    //底盤(pán)類(lèi)
    static class Bottom {
        private Tire tire;
        public Bottom(int size) {
            this.tire = new Tire(size);
            System.out.println("Bottom init...");
        }
    }
    //輪胎類(lèi)
    static class Tire {
        // 尺?
        private int size;
        public Tire(int size){
            this.size = size;
            System.out.println("輪胎尺?:" + size);
        }
    }
}

修改輪胎的構(gòu)造方法之后,底盤(pán)也需要修改,當(dāng)修改底盤(pán)之后,上層調(diào)用也需要修改

而在 IoC 模式下,對(duì)象的創(chuàng)建和管理這些控制權(quán)被反轉(zhuǎn)了,不再由對(duì)象自身來(lái)控制,而是交給外部的容器(IoC 容器)來(lái)管理,下面演示一下使用 IoC 的思想來(lái)管理對(duì)象

public class IocCarExample {
    public static void main(String[] args) {
        Tire tire = new Tire(20);
        Bottom bottom = new Bottom(tire);
        Framework framework = new Framework(bottom);
        Car car = new Car(framework);
        car.run();
    }

通過(guò)這樣的形式,各個(gè)組件的依賴(lài)關(guān)系就發(fā)生了反轉(zhuǎn),統(tǒng)一對(duì)對(duì)象進(jìn)行管理,誰(shuí)需要這個(gè)對(duì)象直接傳過(guò)去一個(gè)對(duì)象,不需要他自己調(diào)用方法進(jìn)行創(chuàng)建

IoC 容器的工作就是把這些對(duì)象進(jìn)行統(tǒng)一管理

通過(guò)這種方式進(jìn)行資源的統(tǒng)一管理,在創(chuàng)建實(shí)例時(shí)不需要了解其中的細(xì)節(jié),降低了使用資源雙方的依賴(lài)程度

3. IoC 容器的使用

3.1. bean 的存儲(chǔ)

如果想要把一個(gè)對(duì)象交給 IoC 容器來(lái)管理,需要在類(lèi)上添加一個(gè) @Component 注解,此外還有其它的一些注解可以實(shí)現(xiàn):

  1. 類(lèi)注解:@Controller、@Service、@Repository、@Component、@Configuration.
  2. 方法注解:@Bean.
@Controller
public class UserController {
    public void say(){
        System.out.println("UserController");
    }
}
@SpringBootApplication
public class SpringIoCApplication {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(SpringIoCApplication.class, args);
        UserController bean = context.getBean(UserController.class);
        bean.say();
    }
}

ApplicationContext 可以理解為 Spring 的上下文,這個(gè)上下文就是指當(dāng)前的運(yùn)行環(huán)境和其他功能,也可以看作是一個(gè)容器,容器中存儲(chǔ)了很多內(nèi)容,這些內(nèi)容是當(dāng)前的運(yùn)行環(huán)境

之后就可以通過(guò)拿到的 context 來(lái)獲取 bean,關(guān)于獲取 bean 有多種方式:

Object getBean(String var1) throws BeansException;

根據(jù)bean名稱(chēng)獲取bean

T getBean(String var1, Class var2) throws BeansException;

根據(jù)bean名稱(chēng)和類(lèi)型獲取bean

T getBean(Class var1) throws BeansException;

根據(jù)類(lèi)型獲取bean

Object getBean(String var1, Object... var2) throws BeansException

按bean名稱(chēng)和構(gòu)造函數(shù)參數(shù)動(dòng)態(tài)創(chuàng)建bean,只適?于具有原型(prototype)作?域的bean

T getBean(Class var1, Object... var2) throws BeansException;

按bean類(lèi)型和構(gòu)造函數(shù)參數(shù)動(dòng)態(tài)創(chuàng)建bean, 只適?于具有原型(prototype)作?域的 bean

根據(jù)類(lèi)型獲取 bean 的話(huà),如果存在多個(gè)相同類(lèi)型的 bean 那么就不能確定具體要獲取的是哪個(gè) bean ,同理,如果只是根據(jù)名稱(chēng)來(lái)獲取 bean,如果重名的話(huà)也是不能正確獲取到 bean 的,所以就有了第三種方式,同時(shí)根據(jù)類(lèi)型和名稱(chēng)來(lái)獲取 bean

上面這三種獲取 bean 的方式是比較常用的

關(guān)于 IoC 中 bean 的名稱(chēng)轉(zhuǎn)化規(guī)則:

如果是 UserController 會(huì)被轉(zhuǎn)成 userController,如果是 UController 就還是 UController

UserController bean1 = (UserController) context.getBean("userController");
bean1.say();

由于是根據(jù)名稱(chēng)來(lái)獲取 bean,所以獲取到的 bean 不確定是什么類(lèi)型,會(huì)返回一個(gè) Object 類(lèi)型,需要強(qiáng)轉(zhuǎn)一下

同時(shí)指定類(lèi)型和名稱(chēng):

UserController bean2 = context.getBean("userController", UserController.class);
bean2.say();

把上面獲取的 bean ,打印一下,發(fā)現(xiàn)獲取的實(shí)例的地址是一樣的,由此可以知道,通過(guò)這種方式獲取對(duì)象是基于單例模式實(shí)現(xiàn)的

接下來(lái)演示一下 @Service 注解:

@Service
public class UserService {
    public void say(){
        System.out.println("UserService");
    }
}
UserService service = context.getBean(UserService.class);
service.say();

然后發(fā)現(xiàn)和上面一樣也是可以運(yùn)行的,其它的幾個(gè)類(lèi)注解也是一樣的

那么為什么實(shí)現(xiàn)的功能一樣,還需要分這么多不同的注解,這個(gè)是和之前的應(yīng)用分層是對(duì)應(yīng)的,通過(guò)不同的類(lèi)注解來(lái)了解當(dāng)前類(lèi)的用途

@Controller:控制層,接受請(qǐng)求,對(duì)請(qǐng)求進(jìn)行處理,并進(jìn)行響應(yīng)

@Servie:業(yè)務(wù)邏輯層,處理具體的業(yè)務(wù)邏輯

@Repository:數(shù)據(jù)訪(fǎng)問(wèn)層, 也稱(chēng)為持久層,負(fù)責(zé)數(shù)據(jù)訪(fǎng)問(wèn)操作

@Configuration:配置層,處理項(xiàng)目中的一些配置信息

3.2. 方法注解@Bean

上面四個(gè)注解都是 @Component的衍生注解

類(lèi)注解是添加到某個(gè)類(lèi)上的,但是存在兩個(gè)問(wèn)題:

  1. 如果使用外部包里的類(lèi),沒(méi)辦法添加注解
  2. 同時(shí),由于類(lèi)注解默認(rèn)創(chuàng)建的對(duì)象是單例對(duì)象,如果需要多個(gè)對(duì)象就需要調(diào)整

方法注解 @Bean就可以解決上述問(wèn)題

例如,在一個(gè)外部包里有一個(gè) UserInfo 類(lèi)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserInfo {
    private String name;
    private Integer age;
}

可以通過(guò)在獲取對(duì)象的方法上加上@Bean

@Component
public class UserInfoComponent {
    @Bean
    public UserInfo userInfo(){
        return new UserInfo("zhangsan",20);
    }
}

如果說(shuō)需要?jiǎng)?chuàng)建對(duì)個(gè)對(duì)象的話(huà):

這個(gè)問(wèn)題就是在獲取 bean 的時(shí)候發(fā)現(xiàn)了具有相同類(lèi)型的 bean,可以直接通過(guò)獲取 bean 的名稱(chēng),這里的名稱(chēng)和方法注解下方法名是對(duì)應(yīng)的

UserInfo bean = (UserInfo) context.getBean("userInfo");
System.out.println(bean);

上面的注解,無(wú)論是類(lèi)注解還是方法注解,都可以實(shí)現(xiàn)重命名

重命名之后就需要使用改之后的名字了

4. 掃描路徑

如果說(shuō)把啟動(dòng)類(lèi)放到其他目錄下再運(yùn)行就會(huì)報(bào)錯(cuò),是因?yàn)樯厦娼榻B的注解如果想要生效,是需要配置掃描路徑的,默認(rèn)的掃描范圍是 Spring Boot 啟動(dòng)類(lèi)所在的包和它的子包,可以通過(guò)@ComponentScan來(lái)配置掃描路徑

@ComponentScan源碼中,是支持傳入一個(gè)數(shù)組的,如果想要配置多個(gè)掃描路徑可以直接傳入一個(gè)數(shù)組

@ComponentScan({"com.example.service","com.example.controller"})

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

相關(guān)文章

  • SpringSecurity rememberme功能實(shí)現(xiàn)過(guò)程解析

    SpringSecurity rememberme功能實(shí)現(xiàn)過(guò)程解析

    這篇文章主要介紹了SpringSecurity rememberme功能實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • SpringBoot集成ENC對(duì)配置文件進(jìn)行加密的流程步驟

    SpringBoot集成ENC對(duì)配置文件進(jìn)行加密的流程步驟

    Spring Boot Encoder,即Spring Boot加密模塊,它提供了一種簡(jiǎn)單的方式來(lái)集成安全編碼功能到Spring Boot應(yīng)用程序中,它是Spring Security框架的一部分,旨在幫助開(kāi)發(fā)者輕松地處理數(shù)據(jù)加密,本文給大家介紹了SpringBoot集成ENC對(duì)配置文件進(jìn)行加密的流程步驟
    2024-12-12
  • 如何將字符串、字節(jié)數(shù)組轉(zhuǎn)為輸入流

    如何將字符串、字節(jié)數(shù)組轉(zhuǎn)為輸入流

    這篇文章主要介紹了如何將字符串、字節(jié)數(shù)組轉(zhuǎn)為輸入流問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java用BigDecimal類(lèi)解決Double類(lèi)型精度丟失的問(wèn)題

    Java用BigDecimal類(lèi)解決Double類(lèi)型精度丟失的問(wèn)題

    這篇文章主要介紹了Java用BigDecimal類(lèi)解決Double類(lèi)型精度丟失的問(wèn)題,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-12-12
  • Spring Boot 中PageHelper 插件使用配置思路詳解

    Spring Boot 中PageHelper 插件使用配置思路詳解

    這篇文章主要介紹了Spring Boot 中PageHelper 插件使用配置及實(shí)現(xiàn)思路,通過(guò)引入myabtis和pagehelper依賴(lài),在yml中配置mybatis掃描和實(shí)體類(lèi),具體實(shí)現(xiàn)方法跟隨小編一起看看吧
    2021-08-08
  • springboot?jpa之返回表中部分字段的處理詳解

    springboot?jpa之返回表中部分字段的處理詳解

    這篇文章主要介紹了springboot?jpa之返回表中部分字段的處理詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java8中Stream的使用以及分割list案例

    java8中Stream的使用以及分割list案例

    這篇文章主要介紹了java8中Stream的使用以及分割list案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • IDEA實(shí)現(xiàn)遠(yuǎn)程調(diào)試步驟詳解

    IDEA實(shí)現(xiàn)遠(yuǎn)程調(diào)試步驟詳解

    這篇文章主要介紹了IDEA實(shí)現(xiàn)遠(yuǎn)程調(diào)試步驟詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • java使用JWT的方法

    java使用JWT的方法

    這篇文章主要介紹了java使用JWT的方法,JWT是token的一種,一個(gè)JWT字符串包含三個(gè)部分分別是Header、Payload和Signature,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • Jmeter內(nèi)置變量vars和props的使用詳解

    Jmeter內(nèi)置變量vars和props的使用詳解

    JMeter是一個(gè)功能強(qiáng)大的負(fù)載測(cè)試工具,它提供了許多有用的內(nèi)置變量來(lái)支持測(cè)試過(guò)程,其中最常用的變量是 vars 和 props,本文通過(guò)代碼示例詳細(xì)給大家介紹了Jmeter內(nèi)置變量vars和props的使用,需要的朋友可以參考下
    2024-08-08

最新評(píng)論