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

Spring使用注解存儲Bean對象的方法詳解

 更新時間:2023年07月28日 10:00:51   作者:韻秋梧桐  
在使用學(xué)習(xí)使用 Spring過程中,當(dāng)我們要實現(xiàn)一個功能的時候,先應(yīng)該考慮的是有沒有相應(yīng)的注解是實現(xiàn)對應(yīng)功能的,Spring 中很多功能的配置都是可以依靠注解實現(xiàn)的,而本篇中介紹的是使用注解來存儲 Bean 對象

通過配置文件注冊對象從而存儲到 Spring 中,這種方式其實還是挺繁瑣的。實際上,在使用學(xué)習(xí)使用Spring過程中,當(dāng)我們要實現(xiàn)一個功能的時候,先應(yīng)該考慮的是有沒有相應(yīng)的注解是實現(xiàn)對應(yīng)功能的,Spring 中很多功能的配置都是可以依靠注解實現(xiàn)的,而本篇中介紹的是使用注解來存儲 Bean 對象。

一. 配置掃描路徑

首先還是要創(chuàng)建 Spring 項目,這里有問題還是去看我上一篇博客。當(dāng)創(chuàng)建好項目后,我們的第一步就是配置掃描路徑,這一步驟非常關(guān)鍵的,這里錯了,之后的的操作就都不會生效了。

我們在resources目錄下創(chuàng)建一個spring-config.xml配置文件,用來設(shè)置掃描的路徑,在配置文件中添加如下內(nèi)容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package=""></content:component-scan>
</beans>

其中<content:component-scan base-package=""></content:component-scan>里面 base-package的值設(shè)置為你需要掃描對象的根路徑,這個路徑從java目錄開始,比如我在如圖中的com.tr.demo目錄下創(chuàng)建類:

img

那么這個配置文件中根路徑就為com.tr.demo,所以我們將base-package的值設(shè)置為com.tr.demo。

<content:component-scan base-package="com.tr.demo"></content:component-scan>

二. 使用注解儲存Bean對象

想要使用注解,那得先知道能使用哪些注解,在 Spring 中有五大類注解和方法注解,分別為:

  • 五大類注解:@Controller(控制器)、@Service(服務(wù))、@Repository(倉庫)、@Component(組件)、@Configuration(配置)。
  • 方法注解:@Bean。

1. 使用五大類注解儲存Bean

首先,我們來了解如何使用五大類注解來儲存對象,先以@Controller注解為例,我們有如下的代碼:

package com.tr.demo;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
    public void sayHi() {
        System.out.println("Hi, UserController~");
    }
}

像這樣在掃描路徑下創(chuàng)建類,并在類上加上@Controller注解就將Bean存儲到容器當(dāng)中了。

接下來就要從 Spring 中讀取出我們的對象,這里還是先使用依賴查找的方式來獲取 Bean,使用五大類注解,默認(rèn)情況下,Bean 的名字就是原類名首字母小寫(小駝峰)。

import com.tr.demo.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class APP {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        //獲取對象時使用類名的小駝峰形式作為 name 參數(shù)
        UserController userController =  context.getBean("userController", UserController.class);
        userController.sayHi();
    }
}

運(yùn)行結(jié)果:

img

要注意,是使用了五大類注解創(chuàng)建的類且類必須要在前面我們配置的掃描路徑下(包括子包)才能將 Bean 存儲到 Spring 當(dāng)中,否則是無效的,所以這個掃描路徑也叫做根路徑。

設(shè)置根路徑其實也是為了提高程序的性能,因為如果不設(shè)置根路徑,Spring 就會掃描項目文件中所有的目錄,但并不是所有類都需要儲存到 Spring當(dāng)中,這樣性能就會比較低,設(shè)置了根路徑,Spring 就只掃描該根路徑下所有的目錄就可以了,提高了程序的性能。

上面只使用了 @Controller,那么我們再來驗證一下其他四個注解可不可以達(dá)到同樣的目的,同時為了驗證上面的結(jié)論,我們在com.tr.demo目錄下再創(chuàng)建一個inner目錄,在根路徑外在創(chuàng)建一個類Student使用類注解。

img

package com.tr.demo.inner;
import org.springframework.stereotype.Component;
@Component
public class UserComponent {
    public void sayHi() {
        System.out.println("Hi, UserComponent~");
    }
}
package com.tr.demo.inner;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfiguration {
    public void sayHi() {
        System.out.println("Hi, UserConfiguration~");
    }
}
package com.tr.demo.inner;
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository {
    public void sayHi() {
        System.out.println("Hi, UserRepository~");
    }
}
package com.tr.demo.inner;
import org.springframework.stereotype.Service;
@Service
public class UserService {
    public void sayHi() {
        System.out.println("Hi, UserService~");
    }
}
import com.tr.demo.UserController;
import com.tr.demo.inner.UserComponent;
import com.tr.demo.inner.UserConfiguration;
import com.tr.demo.inner.UserRepository;
import com.tr.demo.inner.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class APP {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        //獲取對象時使用類名的小駝峰形式作為 name 參數(shù)
        UserController userController =  context.getBean("userController", UserController.class);
        userController.sayHi();
        UserService service =  context.getBean("userService", UserService.class);
        service.sayHi();
        UserConfiguration configuration =  context.getBean("userConfiguration", UserConfiguration.class);
        configuration.sayHi();
        UserComponent component =  context.getBean("userComponent", UserComponent.class);
        component.sayHi();
        UserRepository repository =  context.getBean("userRepository", UserRepository.class);
        repository.sayHi();
    }
}

運(yùn)行結(jié)果:

五大類注解效果都是一樣的,而不在根路徑下的Student是無效的。

img

還需要知道的是使用注解存儲的 Bean 和使用XML存儲的的 Bean 是可以一同使用的,比如我們將將剛剛有問題的Student重新通過XML的方式進(jìn)行存儲。

img

運(yùn)行結(jié)果:

img

2. 為什么要有五大類注解?

既然都五大類完成的是同樣的工作,那為什么要有五大類注解呢?

其實五大類注解主要是為了規(guī)范 Java 項目的代碼,Java 項目的標(biāo)準(zhǔn)分層如下:

  • 控制層(Controller)
  • 服務(wù)層(Service)
  • 數(shù)據(jù)持久層(Dao)

而五大類注解便是對應(yīng)著不同的層級別使用的,讓程序猿看到某一個注解就可以明確這個了類是做什么的。

  • @Controller:控制器,校驗用戶請求數(shù)據(jù)的正確性(安保系統(tǒng));直接和前端打交道,校驗前端發(fā)來請求是參數(shù)和合法性。
  • @Service:服務(wù),編排和調(diào)度具體執(zhí)行方法的(客服中心);不會直接操作數(shù)據(jù)庫,根據(jù)請求判斷具體調(diào)用哪個方法。
  • @Repository:數(shù)據(jù)持久層,直接和數(shù)據(jù)庫交互(實際業(yè)務(wù)的執(zhí)行),也叫DAO層(data access object)。
  • @Component:組件(工具類層),為整個項目存放一些需要使用的組件,但又和其他層沒有什么實際交互。
  • @Configuration 配置項(項目中的一些配置)。

img

包括企業(yè)中也是按照這樣的結(jié)構(gòu)來將項目分層的,典型的比如阿里,它只是在標(biāo)準(zhǔn)分層在服務(wù)層(Service)做了一個擴(kuò)展,劃分的更加細(xì)致詳細(xì)了。

img

五大類注解主要起到的是“見名知意”的作用,代碼層面上來看,作用是類似的,我們?nèi)ゲ榭次宕箢愵愖⒔獾脑创a看一看。

img

img

img

img

img

可以看到五大類的源碼中除了 @Component 以外,其他四大類注解中都包含了 @Component 注解的功能,這四大類注解都是基于 @Component 實現(xiàn)的,是 @Component 拓展。

3.有關(guān)獲取Bean參數(shù)的命名規(guī)則

上文中在使用依賴查找的方式獲取Bean時,getBean方法的BeanName是使用類名的小駝峰形式(即類名的首字母小寫),這是因為使用注解儲存對象時,默認(rèn)會將類名的小駝峰形式設(shè)置為 Bean 的名字,但并不是完全依照這個規(guī)則的,是有特殊情況的。

比如,我們創(chuàng)建一個類,將它的前兩個字母大寫,如UConfig,此時來看使用類名的小駝峰形式還能不能獲取到 Bean。

package com.tr.demo;
import org.springframework.stereotype.Repository;
@Repository
public class UConfig {
    public void sayHi(){
        System.out.println("Hi, UConfig~");
    }
}

啟動類

import com.tr.demo.UConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class APP2 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UConfig uConfig=  context.getBean("uConfig", UConfig.class);
        uConfig.sayHi();
    }
}

運(yùn)行結(jié)果:

img

可以看到程序報錯了,說沒有找到beanNameuConfig的對象,那此時的beanName是什么呢?

此時再來試一下原本的類名(大駝峰),看能不能獲?。?/p>

UConfig uConfig=  context.getBean("UConfig", UConfig.class);

運(yùn)行結(jié)果:

img

此時就獲取到了,好像多少有點玄學(xué)在里面,我們來翻一翻源碼,看一看這是什么原因。

雙擊Shift進(jìn)行全局搜索,上面是根于對象名稱來找到對象的,所以我們輸入beanName,試著搜索一下:

img

我們會發(fā)現(xiàn)有AnnotationBeanNameGenerator類與BeanNameGenerator接口,那我們就試著點到AnnotationBeanNameGenerator類源碼看一看。

正常點開后看到的應(yīng)該是 IDEA 將.class文件反編譯出來的代碼,缺少注釋和明確的變量命名。

img

我們點擊Download Sources將 Spring 源碼下載下來即可,此時我們在在源碼中就能看到下面的方法,看名字也知道,用來建立默認(rèn)的BeanName的。

img

返回值是Introspector.decapitalize方法的返回值,再點進(jìn)去看看這個方法。

img

此時我們就能分析得出結(jié)論,如果類名長度大于1并且滿足第一個與第二個字母為大寫,則構(gòu)造的BeanName就為原類名,其他正常情況為類名的小駝峰形式,這就解釋了UConfig類的BeanName為什么是原類名了。
而且我們會發(fā)現(xiàn)這個方法所在類是來自于jdk的。

img

所以,BeanName的規(guī)范命名規(guī)則并不是 Spring 獨(dú)創(chuàng)的,而依照 Java 標(biāo)準(zhǔn)庫的規(guī)則進(jìn)行的。

  • 如果類名不存在或類名為空字符串,BeanName為原類名。
  • 如果類名字長度大于1,且第一個與第二個字符為大寫,BeanName為原類名。
  • 其他情況,BeanName為原類名的小駝峰形式。

三. 使用方法注解儲存Bean對象

1. 方法注解儲存對象的用法

五大類注解是添加到某個類上的,而方法注解是放到方法上的,當(dāng)一個方法返回的是一個具體的實例對象時,我們就可以使用方法注解@Bean來將對象儲存到 Spring,但是單單使用一個@Bean是不能夠成功儲存對象的,還需要在方法所在類上使用五大類注解才行,比如搭配一 個@Component 注解,方法注解是不能夠單獨(dú)使用的,@Bean注解必須要搭配五大類注解一起使用(Spring為了提升性能所做的規(guī)定,畢竟造方法的成本太低了,不能去掃描整個項目的方法吧)。

還是要注意使用必須是在根路徑下。

比如我們有一個普通文章的實體類ArticleInfo

package com.tr.demo.model;
import java.time.LocalDateTime;
/**
 * 普通的文章實體類
 */
public class ArticleInfo {
    private int aid;
    private LocalDateTime createtime;
    private String title;
    private String author;
    private String content;
    public void setAid(int aid) {
        this.aid = aid;
    }
    public void setCreatetime(LocalDateTime createtime) {
        this.createtime = createtime;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    public void setContent(String content) {
        this.content = content;
    }
    @Override
    public String toString() {
        return "ArticleInfo{" +
                "aid=" + aid +
                ", createtime=" + createtime + "\n" +
                ", title='" + title + '\'' +
                ", author='" + author + '\'' + "\n" +
                ", content='" + content + '\'' +
                '}';
    }
}

下面演示使用@Bean方法注解儲存對象

package com.tr.demo;
import com.tr.demo.model.ArticleInfo;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import java.time.LocalDateTime;
@Controller
public class Articles {
    @Bean// 將當(dāng)前方法返回的對象存儲到 IoC 容器
    public ArticleInfo getArt(){
        // 偽代碼(實際上這里的 Bean 不是 new 出來的)
        ArticleInfo articleInfo = new ArticleInfo();
        articleInfo.setAid(1);
        articleInfo.setCreatetime(LocalDateTime.now());
        articleInfo.setTitle("夏日絕句");
        articleInfo.setAuthor("李清照");
        articleInfo.setContent("生當(dāng)做人杰,死亦為鬼雄。至今思項羽,不肯過江東。");
        return articleInfo;
    }
    public void sayHi(){
        System.out.println("Hi, Articles~");
    }
}

獲取方法注解儲存的對象時,傳入的BeanName參數(shù)值默認(rèn)值就是方法名,我上面的代碼中方法名為getArt,所以獲取時,就使用getArt作為參數(shù)來進(jìn)行獲取。

import com.tr.demo.model.ArticleInfo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class APP3 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        ArticleInfo article =  context.getBean("getArt", ArticleInfo.class);
        System.out.println(article);
    }
}

運(yùn)行結(jié)果:

img

2. @Bean的重命名

獲取方法注解儲存的對象時,傳入的BeanName參數(shù)值默值為方法名,但像上面那樣返回對象的方法名稱往往是getXXX這樣式取名的,雖然在語法與實現(xiàn)上是沒有問題的,但實際開發(fā)寫出這樣的代碼,看起來還是比較別扭的。

實際上注解 @Bean 是可以加參數(shù)的,給儲存的對象起別名,像下面這個樣子。

@Controller
public class Articles {
    @Bean("article")// 將當(dāng)前方法返回的對象存儲到 IoC 容器
    public ArticleInfo getArt(){
        // 偽代碼(實際上這里的 Bean 不是 new 出來的)
        ArticleInfo articleInfo = new ArticleInfo();
        articleInfo.setAid(1);
        articleInfo.setCreatetime(LocalDateTime.now());
        articleInfo.setTitle("夏日絕句");
        articleInfo.setAuthor("李清照");
        articleInfo.setContent("生當(dāng)做人杰,死亦為鬼雄。至今思項羽,不肯過江東。");
        return articleInfo;
    }
    public void sayHi(){
        System.out.println("Hi, Articles~");
    }
}

也可以給 Bean 設(shè)置多個別名,總結(jié)起來有如下幾種方式:

//方式一(省略參數(shù)名的情況下默認(rèn)是name)
@Bean("article1")
//方式二
@Bean(name = "article2")
//方式三
@Bean(value = "article3")
//起多個別名
@Bean(name = {"article4", "article5"})
@Bean(value = {"article6", "article7"})
@Bean({"article8", "article9", "article10"})

我們按照第 9 行的方式設(shè)置,此時獲取方法注解儲存的對象就能夠使用別名來進(jìn)行獲取。

img

import com.tr.demo.model.ArticleInfo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class APP4 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        ArticleInfo article1 =  context.getBean("article6", ArticleInfo.class);
        System.out.println(article1);
        System.out.println("-----------------------------------------------------");
        ArticleInfo article2 =  context.getBean("article7", ArticleInfo.class);
        System.out.println(article2);
        System.out.println("-----------------------------------------------------");
    }
}

運(yùn)行結(jié)果:

img

再想一下,當(dāng)一個 Bean 有別名了,那使用之前那個方法名還能夠獲取到對象嗎?嘗試一下:

import com.tr.demo.model.ArticleInfo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class APP5 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        ArticleInfo article =  context.getBean("getArt", ArticleInfo.class);
        System.out.println(article);
    }
}

運(yùn)行結(jié)果:

此時就能發(fā)現(xiàn)是獲取不到的

img

所以使用 @Bean 存儲對象的beanName命名規(guī)則是,當(dāng)沒有設(shè)置name/value屬性時,此時 Bean 的默認(rèn)名字就是方法名,一旦添加了別名name/value屬性后,就只能通過重命名的別名來獲取 Bean 了,默認(rèn)的使用方法名獲取 Bean 對象就不能使用了。

還要簡單注意一下,@Bean 使用時,同一類如果多個 Bean 使用相同的名稱,此時程序執(zhí)行是不會報錯的,他會根據(jù)類加載順序和類中代碼從上至下的的順序,將第一個 Bean 存放到 Spring 中,但第一個之后的對象就不會被存放到容器中了,也就是只有在第一次創(chuàng)建 Bean 的時候會將對象和 Bean 名稱關(guān)聯(lián)起來,后續(xù)再有相同名稱的Bean存儲時候,容器會自動忽略。

還可以通過類注解 @Order 注解控制類加載順序(值越小,優(yōu)先級越高),進(jìn)而影響 Bean 的存放的先后順序,這些也比較簡單,就不做演示了。

以上就是Spring使用注解存儲Bean對象的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring注解存儲Bean的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot實現(xiàn)單文件與多文件上傳功能

    SpringBoot實現(xiàn)單文件與多文件上傳功能

    這篇文章主要介紹了SpringBoot實現(xiàn)單文件與多文件上傳功能,Spring?MVC對文件上傳做了簡化,而在Spring?Boot中對此做了更進(jìn)一步的簡化,文件上傳變得更為方便,下面開始演示,需要的小伙伴可以參考一下,希望對你有所幫助
    2022-01-01
  • spring mvc 和ajax異步交互完整實例代碼

    spring mvc 和ajax異步交互完整實例代碼

    本篇文章主要介紹了spring mvc 和ajax異步交互完整實例代碼,簡單的AJAX+SpringMVC的異步交互小例子,有興趣的可以了解一下。
    2017-02-02
  • Java數(shù)組的去重

    Java數(shù)組的去重

    這篇文章主要介紹了Java數(shù)組去重,結(jié)合實例形式分析了Java針對數(shù)組的去重,需要的朋友可以參考下,希望能夠給你帶來幫助
    2021-10-10
  • 詳談java 堆區(qū)、方法區(qū)和棧區(qū)

    詳談java 堆區(qū)、方法區(qū)和棧區(qū)

    下面小編就為大家?guī)硪黄斦刯ava 堆區(qū)、方法區(qū)和棧區(qū)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • 詳解Java的MyBatis框架中SQL語句映射部分的編寫

    詳解Java的MyBatis框架中SQL語句映射部分的編寫

    這篇文章主要介紹了Java的MyBatis框架中SQL語句映射部分的編寫,文中分為resultMap和增刪查改實現(xiàn)兩個部分來講解,需要的朋友可以參考下
    2016-04-04
  • java中Instant類使用詳解(附完整實例)

    java中Instant類使用詳解(附完整實例)

    Java中的Instant是一個不可變的類,用于表示時間的單個點,精確到納秒級別,這篇文章主要介紹了java中Instant類使用的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-07-07
  • Spring Security如何優(yōu)雅的增加OAuth2協(xié)議授權(quán)模式

    Spring Security如何優(yōu)雅的增加OAuth2協(xié)議授權(quán)模式

    這篇文章主要介紹了Spring Security如何優(yōu)雅的增加OAuth2協(xié)議授權(quán)模式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • java中如何使用泛型方法比較大小

    java中如何使用泛型方法比較大小

    這篇文章主要介紹了java中如何使用泛型方法比較大小,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 淺談一下Java中的訪問修飾符以及作用

    淺談一下Java中的訪問修飾符以及作用

    這篇文章主要介紹了淺談一下Java中的訪問修飾符以及作用,修飾符修飾的是“被訪問”的權(quán)限,所有修飾符都可以修飾成員變量,方法,構(gòu)造方法,需要的朋友可以參考下
    2023-05-05
  • SpringBoot自動配置之自定義starter的實現(xiàn)代碼

    SpringBoot自動配置之自定義starter的實現(xiàn)代碼

    這篇文章主要介紹了SpringBoot自動配置之自定義starter的實現(xiàn)代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10

最新評論

龙山县| 廉江市| 买车| 长汀县| 光山县| 遂溪县| 贵港市| 仙居县| 建平县| 安化县| 霍邱县| 元江| 隆尧县| 绥中县| 亳州市| 新邵县| 稻城县| 始兴县| 唐海县| 道孚县| 沁水县| 琼结县| 南阳市| 绥芬河市| 平和县| 康马县| 随州市| 五大连池市| 临西县| 雷州市| 英山县| 兴城市| 蒙自县| 盐城市| 镇安县| 肥东县| 偃师市| 资中县| 万盛区| 郁南县| 平定县|