首頁 > 軟體

Spring五大類註解讀取儲存Bean物件的方法

2022-09-04 18:02:20

前情提要

我們上節內容學習瞭如何建立註冊讀取bean
我們發現bean物件操作十分的繁瑣!
所以我們這個章節,就帶大家來了解更加簡單的bean操作,通過Spring下的註解來實現!

設定spring-config檔案

我們之前註冊bean是通過在xml組態檔中,通過鍵值對的方式註冊bean物件!
顯然這種方式很麻煩,註冊一個物件,就要新增一項!
有沒有什麼好的方式可以讓spring直接去註冊物件!
yes!

我們可以直接在組態檔設定好 spring下你要註冊物件的包時那個!
spring啟動後,spring就會將bean物件自動註冊!

spring-config組態檔

<?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">
       <!--在com包下掃描bean註冊-->
        <content:component-scan base-package="com"></content:component-scan>
</beans>

當然只有一個組態檔顯然不夠嘛!
我們如何知道我們程式碼中的物件是bean物件捏?
這就要引入spring五大註解概念了!
我們通過在我們建立好的物件上面新增註解的方式,就是告訴spring這個物件需要註冊到容器中!

類註解和方法註解

類註解:

@Controller@Service@Repository@Component@Configuration

方法註解:
@Bean

我們可以通過上述兩種註解將物件儲存到Spring中!

@Controller(控制器儲存)

使用@Controller註解儲存bean

package com;
import org.springframework.stereotype.Controller;
@Controller //通過Controller註解儲存bean物件
public class UserController {
    public void sayHi(){
        System.out.println("hello Controller註解!");;
    }
}

我們通過在UserController類上加上spring類註解,即可完成註冊物件!

在啟動類中讀取bean物件即可!

//啟動類
public class app{
    public static void main(String[] args) {
        //1.獲取上下文物件
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        //讀取bean物件!
        UserController userController =
                (UserController) context.getBean("userController");
        //使用
        userController.sayHi();
    }
}

如果我們的需要註冊的bean物件不在掃描包下,是否又能註冊成功呢?

我們在新建一個controller包在其下建立TestController類,並且通過@Controller註冊到Spring中!

package controller;
import org.springframework.stereotype.Controller;
@Controller //註冊到Spring中!
public class TestController {
    public void sayHi(){
        System.out.println("該bean不在掃描的包下");
    }
}

然後我們通過ApplicationContext上下文物件讀取bean

可以看到出現異常未找到名為textControllerbean物件!

結論:只有在掃描包下的類才能被Spring註冊

@Service(服務儲存)

註冊bean

package com;

import org.springframework.stereotype.Service;

@Service // @Service 註解註冊物件!
public class UserService {
    public  void sayHi(){
        System.out.println("Hello Service註解!");
    }
}

讀取bean

@Configuration(設定儲存)

package com;
import org.springframework.context.annotation.Configuration;
@Configuration //Configuration註解註冊bean物件
public class UserConfiguration {
    public void sayHi(){
        System.out.println("Hello Configuration註解!");
    }
}

@Repository(倉庫儲存)

package com;

import org.springframework.stereotype.Repository;

@Repository //@Respository 註解註冊物件
public class UserRepository {
    public void sayHi(){
        System.out.println("Hello Respository註解!");
    }
}

@Component(元件儲存)

package com;

import org.springframework.stereotype.Component;

@Component //Component註解註冊物件!
public class UserComponent {
    public void sayHi(){
        System.out.println("Hello Component註解!");
    }
}

5大類註解聯絡

可以看到這5大類註解使用方式一樣,都可以對物件進行註冊!
而且註冊的方式都一樣,既然如此為何還需要5個註解呢?

我們聯絡實際生活中的車牌號,我們雖然車牌號的功能都是一樣,但是不同地區都有自己的車牌號!我們通過車牌號就可以分辨出這車來自哪裡!
而這裡5大類註解作用也是如此,我們通過類註解,可以知道當前類的用途!
例如;

@Controller:表示業務邏輯層
@Service:服務層
@Repository:持久層
@Configuration:設定層

程式的工程分層,呼叫流程如下:

我們拿去銀行辦業務做類比:

@Controller層就是保安,先要進行檢查驗證,然後到達Service服務廳詢問業務,不同的業務來到Repository,不同的視窗,然後進行相應的工作人員辦理業務!

類註解之前聯絡:

可以看到其他4個註解都是Component註解的子類!

Spring給Bean命名規則

我們可以看到我們剛剛讀取bean物件時,我們並不知道bean物件註冊的id而是直接通過userController讀取!
難道說Spring註冊bean物件id為類名首字母小寫,直接就小駝峰?

我們檢視Spring原始碼驗證!

我們順藤摸瓜下方就是Spring對Bean物件進行命名的方法!

 public static String decapitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        }
        if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                        Character.isUpperCase(name.charAt(0))){
            return name;
        }
        char chars[] = name.toCharArray();
        chars[0] = Character.toLowerCase(chars[0]);
        return new String(chars);
    }

可以看到我們這裡bean物件的id命名規則如下:

物件類類名一般採用大駝峰的形式也就是單詞第一個字母大小,所以Spring直接bean物件改為小駝峰,`第一個字母分成小寫!物件類類名不規範,不是大駝峰,第二個字母和第一個字母都是大小!Spring直接將bean物件命名為類名!

我們進行驗證:

方法註解@Bean

我們瞭解了5大類註解可以進行物件註冊,我們使用方法註解進行物件註冊!
注意: 方法註解要和類註解配合使用!

方法註解進行物件註冊

//User類
public class User {
    private String name;
    private int id;
    public User(String name, int id) {
        this.name = name;
        this.id = id;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + ''' +
                ", id=" + id +
                '}';
    }
}
//Users類
@Component
public class Users {
    @Bean
    public User user(){
        return new User("java",666);
    }
}

可以看到@Bean註解適用於返回值返回物件的方法中!

重新命名Bean

我們既然可以通過五大類註解進行物件注入!那為何還要多此一舉在方法上加上@Bean方法註解呢?

我們可以通過@Bean方法註解給bean物件重新命名,可以直接設定名字!

通過 name={"rename1", "rename2"...}可以重新命名多個!

@Component
public class Users {
    @Bean(name = {"user1"})
    public User user(){
        return new User("java",666);
    }
}

能否通過之前Spring給我們設定的名字存取? 不能

@Bean(name={"user1","user2"}) 重新命名多個!

我們也可以將name省略
@Bean({"user1"})

獲取Bean物件(物件裝配)

這裡可能聽了有點迷,啥玩意物件裝配,其實就是獲取物件!
我們將物件註冊到Spring容器下,我們要讀取將物件取出放入到某個類中,這就是物件裝配,也叫物件注入!

實現物件裝配的3種方法

  • 屬性注入
  • 構造方法注入
  • Setter注入

下面我們來演示一下這3種注入方式

我們按照實際開發將Service層的類注入到Controller層的類中!

屬性注入

我們通過@Autowired實現屬性注入
service層類程式碼

@Service
public class UserService {
    public User getUser(){
        return new User("Mysql",666);
    }
}

controller層類程式碼
通過屬性注入將service層程式碼注入到這

@Controller
public class UserController {
    //屬性注入
    @Autowired
    private UserService userService;
    public User getUser(){
        return userService.getUser();
    }
}

執行結果:

構造方法注入

我們還是通過@Autowired註解注入

@Controller
public class UserController {

    private UserService userService;
    //構造方法注入
    @Autowired
    public UserController(UserService userService){
        this.userService = userService;
    }
    public User getUser(){
        return userService.getUser();
    }
}

Setter注入

@Controller
public class UserController {
    //Setter注入
    private UserService userService;
    @Autowired
    public void setUserService(UserService userService){
        this.userService = userService;
    }
    public User getUser(){
        return userService.getUser();
    }
}

三種注入方式對比

  • 屬性注入簡潔,使用方便! 缺點只能適用於IoC容器,在非IoC容器不適用,並且屬性注入只有在是使用的時候才會出現空指標異常(NPE)
  • 構造方法注入現在官方推薦注入方式! 缺點 如果注入多個物件,就會使得程式碼臃腫,不過這就是程式設計師的問題了,不符合程式設計的單一職責的設計模式,優點通用性強,在使用前一定可以保證注入的類不為空!
  • Setter方式是Spring前期推薦的注入方式,通用性不如構造方法注入,現在已經認準構造方法注入!

在進行類注入時,我們還可以通過@Resource註解進行注入!
我們只需要將@Autowired註解換成@Resource即可!

@Autowired@Resource區別

  • 出身不同: @Autowired註解是Spring提供的,@Resource是來自JDK下的註解
  • 使用設定的引數不同:相比@Autowired註解,@Resource註解 支援更多的引數設定 例如name設定,根據name獲取物件

注入同一型別多個Bean物件

我們在Users類中註冊了2個相同型別的Bean物件!

@Component
public class Users {
    @Bean(name = "user1")
    public User user1(){
        User user =  new User("java",666);
        return user;
    }
    @Bean(name = "user2")
    public User user2(){
        User user = new User("MySQL",666);
        return user;
    }
}

當我們直接注入到Controller類中!

@Controller
public class UserController {
    @Resource
    private User user;
    public User getUser(){
        return user;
    }
}

因為我們在Spring中註冊了2個相同型別的User物件,所以進行物件裝配時,也需要通過name屬性進行宣告你要裝配的物件名!

@Controller
public class UserController {
    @Resource(name = "user2")
    private User user;
    public User getUser(){
        return user;
    }
}

注意:

@Resource註解才提供了name屬性,如果用@Autowried需要加上@Qualifier 註解定義名稱

@Controller
public class UserController {
//    @Resource(name = "user2")
    @Autowired
    @Qualifier(value = "user1")
    private User user;
    public User getUser(){
        return user;
    }
}

到此這篇關於Spring五大類註解讀取儲存Bean物件的文章就介紹到這了,更多相關Spring 讀取儲存Bean物件內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com