溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Spring中的Bean怎么使用

發(fā)布時(shí)間:2023-03-22 15:25:51 來(lái)源:億速云 閱讀:126 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本文小編為大家詳細(xì)介紹“Spring中的Bean怎么使用”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“Spring中的Bean怎么使用”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來(lái)學(xué)習(xí)新知識(shí)吧。

    從廣義上 Spring 注解可以分為兩類(lèi):

    • 一類(lèi)注解是用于注冊(cè) Bean

    假如 IoC 容器是一間空屋子,首先這間空屋子啥都沒(méi)有,我們要吃大餐,我們就要從外部搬運(yùn)食材和餐具進(jìn)來(lái)。這里把某一樣食材或者某一樣餐具搬進(jìn)空屋子的操作就相當(dāng)于每個(gè)注冊(cè) Bean 的注解作用類(lèi)似。注冊(cè) Bean 的注解作用就是往 IoC容器中放(注冊(cè))東西!

    用于注冊(cè) Bean 的注解:比如 @Component、@Repository、@Controller、@Service、@Configuration 這些注解就是用于注冊(cè) Bean,放進(jìn) IoC 容器中,一來(lái)交給 Spring 管理方便解耦,二來(lái)還可以進(jìn)行二次使用,啥是二次使用呢?這里的二次使用可以理解為:在你開(kāi)始從外部搬運(yùn)食材和餐具進(jìn)空屋子的時(shí)候,一次性搬運(yùn)了豬肉、羊肉、鐵勺、筷子四樣?xùn)|西,這個(gè)時(shí)候你要開(kāi)始吃大餐,首先你吃東西的時(shí)候肯定要用筷子或者鐵勺,別說(shuō)你手抓,只要你需要,你就會(huì)去找,這個(gè)時(shí)候發(fā)現(xiàn)你已經(jīng)把筷子或者鐵勺放進(jìn)了屋子,你就不同再去外部拿筷子進(jìn)屋子了,意思就是 IoC 容器中已經(jīng)存在,就可以直接拿去用,而不必再去注冊(cè)!而拿屋子里已有的東西的操作就是下面要講的關(guān)于使用 Bean 的注解!

    • 一類(lèi)注解是用于使用 Bean

    用于使用 Bean 的注解:比如 @Autowired、@Resource 注解,這些注解就是把屋子里的東西自己拿來(lái)用,如果你要拿,前提一定是屋子(IoC)里有的,不然就會(huì)報(bào)錯(cuò)。比如你要做一道牛肉拼盤(pán)需要五頭牛做原材料才行,你現(xiàn)在鍋里只有四頭牛,這個(gè)時(shí)候你知道,自己往屋子里搬過(guò)五頭牛,這個(gè)時(shí)候就直接把屋子里的那頭牛直接放進(jìn)鍋里,完成牛肉拼盤(pán)的組裝。是的這些注解就是需要啥,只要容器中有就往容器中拿,就是這么豪橫!而這些注解又有各自的區(qū)別,比如 @Autowired 用在筷子上,這筷子你可能想用木質(zhì)的,或許只想用鐵質(zhì)的,@Autowired 作用在什么屬性的筷子就那什么筷子,而 @Resource 如果用在安格斯牛肉上面,就指定要名字就是安格斯牛肉的牛肉。

    一、定義

    Bean 是 Spring 框架中最核心的兩個(gè)概念之一(另一個(gè)是面向切面編程 AOP)

    Spring 官方文檔對(duì) bean 的解釋是:

    In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container.

    翻譯過(guò)來(lái)就是:

    在 Spring 中,構(gòu)成應(yīng)用程序主干并由 Spring IoC 容器管理的對(duì)象稱(chēng)為 bean。bean 是由Spring IoC 容器實(shí)例化、組裝和管理的對(duì)象。

    從上面翻譯過(guò)來(lái)意思來(lái)看:

    • bean 是對(duì)象,一個(gè)或者多個(gè)不限定

    • bean 由 Spring 中一個(gè)叫 IoC 的東西管理的

    • 我們的應(yīng)用程序由一個(gè)個(gè) bean 構(gòu)成

    那么問(wèn)題來(lái)了,IoC 是什么呢?

    二、控制反轉(zhuǎn)(IoC)

    控制反轉(zhuǎn)英文全稱(chēng):Inversion of Control,簡(jiǎn)稱(chēng)就是 IoC。控制反轉(zhuǎn)通過(guò)依賴(lài)注入(DI)方式實(shí)現(xiàn)對(duì)象之間的松耦合關(guān)系。程序運(yùn)行時(shí),依賴(lài)對(duì)象由輔助程序動(dòng)態(tài)生成并注入到被依賴(lài)對(duì)象中,動(dòng)態(tài)綁定兩者的使用關(guān)系。Spring IoC 容器就是這樣的輔助程序,它負(fù)責(zé)對(duì)象的生成和依賴(lài)的注入,然后再交由我們使用。

    1、什么是依賴(lài)注入與控制反轉(zhuǎn)呢?先通過(guò)一個(gè)例子來(lái)理解一下

    首先有一個(gè)類(lèi)叫做 Student,里面有兩個(gè)成員變量分別是 id 和 name,并提供 set、get方法。

    public class Student {
        private Integer id;
        private String name;
     
        public Integer getId() {
            return id;
        }
     
        public void setId(Integer id) {
            this.id = id;
        }
     
        public String getName() {
            return name;
        }
     
        public void setName(String name) {
            this.name = name;
        }
    }

    另外一個(gè)類(lèi)叫做 StudentManager

    public class StudentManager {
        private Student student;
     
        public void setStudent(Student student) {
            this.student = student;
        }
     
        public void show() {
            System.out.println(student.getId());
            System.out.println(student.getName());
        }
    }

            這個(gè) StudentManager 類(lèi)有個(gè)成員是 Student 的一個(gè)對(duì)象,然后它的 show 方法能夠打印這個(gè) student 的 id 以及 name,并提供了 setStudent 方法初始化 Student 對(duì)象。我們可以說(shuō),StudentManager(被依賴(lài)對(duì)象) 是依賴(lài)于 Student(依賴(lài)對(duì)象)的。

            有一個(gè)問(wèn)題,StudentManager 與 Student 之間的耦合非常緊密,假如我們還沒(méi)有來(lái)的及對(duì) StudentManager 的 student 綁定對(duì)象,卻調(diào)用了 show 方法的話(huà),那么程序?qū)?huì)拋出空指針異常。所以 Spring 提供了一套叫做控制反轉(zhuǎn)與依賴(lài)注入這套機(jī)制,目的就是為了解耦。

            在 Spring 中,你不需要自己創(chuàng)建對(duì)象,你只需要告訴 Spring,哪些類(lèi)我需要?jiǎng)?chuàng)建出對(duì)象,然后在啟動(dòng)項(xiàng)目的時(shí)候 Spring 就會(huì)自動(dòng)幫你創(chuàng)建出該對(duì)象,并且只存在一個(gè)類(lèi)的實(shí)例。這個(gè)類(lèi)的實(shí)例在 Spring 中被稱(chēng)為 Bean。而這種模式,我們稱(chēng)之為“單例模式”。也就是一個(gè)類(lèi)只有一個(gè)實(shí)例的意思。

            那么 Spring 是靠什么來(lái)了解究竟哪些類(lèi)需要幫我們創(chuàng)建呢,這里介紹最常用的兩種方式------Java 注解配置,Java 代碼配置。之前還有 XML 配置等,但是之前的現(xiàn)在已經(jīng)不推薦使用了。

            首先介紹的是 Java 注解配置,這是最簡(jiǎn)單也是最常用的一種方式。

    聲明含義
    @Component當(dāng)前類(lèi)是組件,沒(méi)有明確的意思
    @Service當(dāng)前類(lèi)在業(yè)務(wù)邏輯層使用
    @Repository當(dāng)前類(lèi)在數(shù)據(jù)訪(fǎng)問(wèn)層
    @Controller當(dāng)前類(lèi)在展示層(MVC)使用

            以上四種聲明方式效果完全一致,使用不同的關(guān)鍵詞是為了給閱讀的人能夠快速了解該類(lèi)屬于哪一層。

            使用方法為:在定義的實(shí)體類(lèi)前使用該注解。讓我們看下面一段代碼

    @Component
    public class Student {
        private Integer id;
        private String name;
     
        public Integer getId() {
            return id;
        }
     
        public void setId(Integer id) {
            this.id = id;
        }
     
        public String getName() {
            return name;
        }
     
        public void setName(String name) {
            this.name = name;
        }
    }

            我們?cè)趧偛诺?Student 類(lèi)前面,加上了 @Component 注解,成功告訴 Spring:你要在項(xiàng)目創(chuàng)建運(yùn)行時(shí)幫我創(chuàng)建 Student 類(lèi)的 Bean (對(duì)象)

            好了,這時(shí)候添加“依賴(lài)”就已經(jīng)做完了,但是還沒(méi)完,我們雖然讓 Spring 幫我們創(chuàng)建了對(duì)象,但是 StudentManager 怎么知道這個(gè)對(duì)象在哪呢?所以接下來(lái),我們要告訴 StudentManager 剛才 Spring 幫我們創(chuàng)建的 Bean (對(duì)象)到底在哪,也就是使用(“注入”)這個(gè) Bean。

            我們來(lái)看看注入注解的語(yǔ)法:

    聲明含義
    @Autowired根據(jù) Bean 的 Class 類(lèi)型來(lái)自動(dòng)裝配
    @Inject翻譯為“注入”最易懂得注入注解
    @Resource翻譯為“資源”,根據(jù) Bean 得屬性名稱(chēng)(id 或 name)自動(dòng)裝配

            使用方法:在我們需要注入依賴(lài)的成員變量前使用該注解,看一下下面一段代碼

    @Component
    public class StudentManager {
        @Autowired
        private Student student;
     
        public void show() {
            System.out.println(student.getId());
            System.out.println(student.getName());
        }
    }

            可以看到,在聲明成員變量 Student 的前面我們使用了 @Autowired,所以 Spring 會(huì)自動(dòng)幫我們使用(注入)一個(gè) Bean,我們就再也不用擔(dān)心忘記綁定對(duì)象而出現(xiàn)空指針了。但是可以發(fā)現(xiàn),雖然我們告訴了 Spring 哪些類(lèi)是需要添加依賴(lài),哪些類(lèi)是需要注入 Bean,但是 Spring 還需要我們做一次配置,來(lái)真正完成這樣一個(gè)操作。

    2、讓 Spring 控制類(lèi)構(gòu)建過(guò)程

    不用 new,讓 Spring 控制 new 過(guò)程。在 Spring 中,我們基本不需要 new 一個(gè)類(lèi),這些都是讓 Spring 去做的。Spring 啟動(dòng)時(shí)會(huì)把所需的類(lèi)實(shí)例化對(duì)象,如果需要依賴(lài),則先實(shí)例化依賴(lài),然后實(shí)例化當(dāng)前類(lèi)。因?yàn)橐蕾?lài)必須通過(guò)構(gòu)建函數(shù)傳入,所以實(shí)例化時(shí),當(dāng)前類(lèi)就會(huì)接收并保存所有依賴(lài)的對(duì)象。這一步也就是所謂的依賴(lài)注入。

    3、這就是 IOC

    在 Spring 中,類(lèi)的實(shí)例化、依賴(lài)的實(shí)例化、依賴(lài)的傳入都交由 Spring Bean 容器控制,而不是用 new 方式實(shí)例化對(duì)象、通過(guò)非構(gòu)造函數(shù)方法傳入依賴(lài)等常規(guī)方式。實(shí)質(zhì)的控制權(quán)已經(jīng)交由程序管理,而不是程序員管理,所以叫控制反轉(zhuǎn)。

    三、 @Bean 注解的使用

    1、使用說(shuō)明

    • @Bean 注解作用在方法上,產(chǎn)生一個(gè) Bean 對(duì)象,然后這個(gè) Bean 對(duì)象交給 Spring 管理,剩下的你就不用管了。產(chǎn)生這個(gè) Bean 對(duì)象的方法 Spring 只會(huì)調(diào)用一次,隨后這個(gè) Spring 將會(huì)將這個(gè) Bean 對(duì)象放在自己的 IOC 容器中。

    • @Bean 方法名與返回類(lèi)名一致,首字母小寫(xiě)。

    • @Component、@Repository、@Controller、@Service 這些注解只局限于自己編寫(xiě)的類(lèi),而 @Bean 注解能把第三方庫(kù)中的類(lèi)實(shí)例加入 IOC 容器中并交給 Spring 管理。

    • @Bean 一般和 @Component 或者 @Configuration 一起使用

    2、Bean 名稱(chēng)

    2.1、默認(rèn)情況下 Bean 名稱(chēng)就是方法名(首字母小寫(xiě)),比如下面 Bean 名稱(chēng)便是 myBean
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
    2.2、@Bean 注解支持設(shè)置別名。比如下面除了主名稱(chēng) myBean 外,還有個(gè)別名 myBean1(兩個(gè)都可以使用)
    @Bean("myBean1")
    public MyBean myBean() {
        return new MyBean();
    }
    2.3、@Bean 注解可以接受一個(gè) String 數(shù)組設(shè)置多個(gè)別名。

    比如下面除了主名稱(chēng) myBean 外,還有別名 myBean1、myBean2(三個(gè)都可以使用)

    @Bean({"myBean1","myBean2"})
    public MyBean myBean() {
        return new MyBean();
    }

    3、@Bean 與其他注解產(chǎn)生的火花

    @Bean 注解常常與 @Scope、@Lazy、@DependsOn 和 @link Primary 注解一起使用

    3.1、@Profile 注解

    為在不同環(huán)境下使用不同的配置提供了支持,如開(kāi)發(fā)環(huán)境和生產(chǎn)環(huán)境的數(shù)據(jù)庫(kù)配置是不同的

    @Bean
    @Profile("!dev")  // 不是dev環(huán)境的能使用這個(gè)bean
    public MyBean myBean() {
        MyBean myBean = new MyBean();
        myBean.setPort("8080");
        return myBean;
    }
    3.2、@Scope 注解

    在 Spring 中對(duì)于 bean 的默認(rèn)處理都是單例的,我們通過(guò)上下文容器.getBean方法拿到 bean 容器,并對(duì)其進(jìn)行實(shí)例化,這個(gè)實(shí)例化的過(guò)程其實(shí)只進(jìn)行一次,即多次 getBean 獲取的對(duì)象都是同一個(gè)對(duì)象,也就相當(dāng)于這個(gè) bean 的實(shí)例在 IOC 容器中是 public 的,對(duì)于所有的 bean 請(qǐng)求來(lái)講都可以共享此 bean。@Scope 注解將其改成 prototype 原型模式(每次獲取 Bean 的時(shí)候會(huì)有一個(gè)新的實(shí)例)

    @Bean
    @Scope("prototype")
    public MyBean myBean() {
        MyBean myBean = new MyBean();
        myBean.setPort("8080");
        return myBean;
    }
    @SpringBootApplication
    @MapperScan("com.example.quartzdemo.dao")//使用MapperScan批量掃描所有的Mapper接口;
    public class QuartzDemoApplication {
        public static void main(String[] args) {
            ConfigurableApplicationContext context = SpringApplication.run(QuartzDemoApplication.class, args);
            MyBean myBean = (MyBean) context.getBean("myBean");
            System.out.println(myBean);
            MyBean myBean2 = (MyBean) context.getBean("myBean");
            System.out.println(myBean2);
        }
    }

    打印輸出結(jié)果:

    com.example.quartzdemo.config.MyBean@49601f82
    com.example.quartzdemo.config.MyBean@23e44287

    將 @Scope("prototype") 刪除掉,再運(yùn)行啟動(dòng)類(lèi),打印結(jié)果如下:

    com.example.quartzdemo.config.MyBean@4cdd2c73
    com.example.quartzdemo.config.MyBean@4cdd2c73

    3.3、@Lazy 注解:

    在 Spring 框架中,默認(rèn)會(huì)在啟動(dòng)時(shí)會(huì)創(chuàng)建所有的 Bean 對(duì)象,但有些 bean 對(duì)象假如長(zhǎng)時(shí)間不用,啟動(dòng)時(shí)就創(chuàng)建對(duì)象,會(huì)占用其內(nèi)存資源,從而造成一定的資源浪費(fèi),此時(shí)我們可以基于懶加載策略延遲對(duì)象的創(chuàng)建。

        @Bean
        @Lazy
        public MyBean myBean() {
            MyBean myBean = new MyBean();
            myBean.setPort("8080");
            return myBean;
        }
    3.4、@DependsOn注解:

    表示在當(dāng)前 Bean 創(chuàng)建之前需要先創(chuàng)建特定的其他 Bean

    四、Bean 規(guī)范

    • 所有屬性為 private

    • 提供默認(rèn)構(gòu)造方法

    • 提供 getter 和 setter

    • 實(shí)現(xiàn) Serializable (比如可以實(shí)現(xiàn)Serializable 接口,用于實(shí)現(xiàn)bean的持久性)

    • 屬性類(lèi)型使用包裝類(lèi)

    讀到這里,這篇“Spring中的Bean怎么使用”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過(guò)才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI