日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Spring 的存儲和獲取Bean

作者:CHJBL 更新時間: 2024-01-29 編程語言

文章目錄

  • 獲取 Spring 上下文對象的方式
  • 存儲 Bean 對象的方式
    • 類注解
      • 配置掃描路徑(必須)
      • @Controller(控制器存儲)
      • @Service(服務)
      • @Repository(持久層)
      • @Component(工具)
      • @Configuration(項目中的一些配置)
      • 關于五大類注解
    • 方法注解
  • 獲取指定的 Bean 對象的方式
    • 普通方式
    • 對象注入
      • 屬性注入
      • 構造方法注入
      • Setter 注入
      • @Resource:另?種注入關鍵字
      • 總結

獲取 Spring 上下文對象的方式

首先獲取 Bean 對象之前都需要先獲取 Spring 的上下文對象,那么獲取這個對象可以有以下方式

ApplicationContext context =
		new ClassPathXmlApplicationContext("spring-config.xml");

BeanFactory factory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));

那么這兩者之間有什么區別呢,現在新建兩個 Bean 類運行起來后看結果:

1、ApplicationContext

image-20240125172346756

2、BeanFactory

image-20240125172539215

兩者的運行結果是不一樣的,通過 BeanFactory 實例出來的并不會將 Teacher 對象放入 Spring

ApplicationContext 和 BeanFeactory:

  1. ApplicationContext 會將 xml文件中所聲明需要注冊到Spring中的 Bean 一次性全部注冊完成,而BeanFactory 則是在首次去獲取某一個Bean 對象時才會去注冊該對象
  2. ApplicationContext 比較廢內存但是之后的讀取會很快
  3. BeanFeactory 比較省內存但是效率較低
  4. ApplicationContext 是 BeanFeactory 的子類,ApplicationContext 還擁有獨特的特性, 添加了對國際化支持、資源訪問支持、以及事件傳播等方面的支持

存儲 Bean 對象的方式

基本的存儲方式需要在 spring-config.xml 文件中去添加指定的 Bean 注冊內容才行,這樣就很麻煩。

類注解

配置掃描路徑(必須)

首先在進行注解前需要先配置好路徑,在 spring-config.xml 中添加下面的代碼

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

base-package中添加的是一串路徑,也就是聲明這個路徑下的包中的 Bean 是有可能需要存入到 Spring 中的。注意只是有可能,開始的時候并沒有立即注冊存放到 Spring 中。

@Controller(控制器存儲)

驗證用戶請求的數據正確性,相當于“安保系統”

Student類

import org.springframework.stereotype.Controller;

@Controller // 將當前類存儲到 Spring 中
public class Student {
    public Student(){
        System.out.println("Student init");
    }

    public void print(String str){
        System.out.println(str);
    }
}

啟動類

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import spring.demo.Student;

public class Start {
    public static void main(String[] args) {
        // 獲取 Spring 的上下文對象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 獲取 Bean 對象
        Student student = (Student) context.getBean("student", Student.class);
        // 使用 Bean 對象
        student.print("hello world");
    }
}

因為使用了注解后并沒有指定id屬性,這時需要將id屬性寫為類名的小駝峰形式,這是一個“約定”。

但是也有特例:

? 原類名如果首字母和第二個字母都是大寫的話,id屬性的名稱就和原類名相同

@Service(服務)

編排和調度具體執行方法,相當于“客服中心”

Student類

@Service // 將當前類存儲到 Spring 中
public class Student {
    public Student(){
        System.out.println("Student init");
    }

    public void print(String str){
        System.out.println(str);
    }
}

這樣也同樣可以執行程序

@Repository(持久層)

和數據庫進行交互,是一個“執行者”(DAO)

Student類

@Repository // 將當前類存儲到 Spring 中
public class Student {
    public Student(){
        System.out.println("Student init");
    }

    public void print(String str){
        System.out.println(str);
    }
}

這樣也同樣可以執行程序

@Component(工具)

主要是注解工具類

Student類

@Component // 將當前類存儲到 Spring 中
public class Student {
    public Student(){
        System.out.println("Student init");
    }

    public void print(String str){
        System.out.println(str);
    }
}

這樣也同樣可以執行程序

@Configuration(項目中的一些配置)

Student類

@Configuration // 將當前類存儲到 Spring 中
public class Student {
    public Student(){
        System.out.println("Student init");
    }

    public void print(String str){
        System.out.println(str);
    }
}

這樣也同樣可以執行程序

關于五大類注解

  1. 如果遇到同一個包中有 同名的類 那么可以在使用注解時使用例如 @Controller(value = “XXX”) 這種方式去分別,但是建議一個包中盡量不要有同名類
  2. 五大注解的關系:事實上五大注解都是基于 Component 實現的,也就是它們都是 Component 的“子類”,是對于 Component 的擴展。那么需要分出這么多類注解的原因就是讓程序員看到類注解之后,就能直接了解當前類的用途

方法注解

方法注解就是在一個有返回值的方法上加上 @Bean 注解的方式,也就是說 Spring 會將有著 @Bean 注解的方法的返回值的對象存入

需要注意:

  1. @Bean 注解需要配合五大類注解使用
  2. 使用了@Bean 注解后,默認的 Bean 對象ID屬性為該具有 @Bean 注解的方法名
  3. 可以使用 @Bean(name = {“XXX”})的形式去設置這個 Bean 對象的ID屬性。并且這個重命名的 name 其實是?個數組,一個 Bean 可以有多個名字,例如 @Bean(name = {“XXX”, “XXX”})。并且 name= 是可以去掉的,例如 @Bean({“XXX”, “XXX”})
@Component
public class UserBeans {
    @Bean({"user"})
    public User getUser(){
        User user = new User();
        user.setId(1);
        user.setName("張三");
        return user;
    }
}
public class Start {
    public static void main(String[] args) {
        // 獲取 Spring 的上下文對象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 獲取 Bean 對象
        User user = context.getBean("user", User.class);
        // 使用 Bean 對象
        System.out.println(user.getName());
    }
}

image-20240126175928869

獲取指定的 Bean 對象的方式

獲取到上下文對象之后就可以通過調用該對象的 getBean方法去獲取 Bean 對象

普通方式

首先常規的就是使用加載時設置的 id 屬性去獲取

Student student = (Student) context.getBean("student");

需要注意這種方式的返回值是 Object 類的,因此需要強轉為 Bean 對象的類

第二種方式可以通過 Bean類的.class 加上 id 屬性去獲取

Student student = context.getBean("student", Student.class);

這樣寫法就比較優美

第三種方式可以直接通過 .class去獲取,但是存在隱患

Student student = context.getBean(Student.class);

存在什么隱患呢,首先一個 Bean類是可以存放多個對象到 Spring 中的,也就是可以這樣

<bean id="student" class="spring.demo.Student"></bean>
<bean id="student2" class="spring.demo.Student"></bean>

那么如果還使用第三種方式就會出現,編譯器不知道具體是要獲取哪一個對象,就會報錯

image-20240125174238394

因此不建議使用這種方式

對象注入

在 Spring 中實現依賴注入的常見方式有以下 3 種:

  1. 屬性注入(Field Injection);
  2. 構造方法注入(Constructor Injection);
  3. Setter 注入(Setter Injection)。

屬性注入

屬性注?是使? @Autowired 實現的,例如下列代碼

// UserService

@Service
public class UserService {
    public void print(){
        System.out.println("hello");
    }
}
// UserController

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    public void print(){
        userService.print();
    }
}
// Start

public class Start {
    public static void main(String[] args) {
        // 獲取 Spring 的上下文對象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 獲取 Bean 對象
        UserController user = context.getBean("userController", UserController.class);
        // 使用 Bean 對象
        user.print();
    }
}

image-20240126180319147

首先可以看到 UserService 和 UserController 這兩個類都是加了類注解的,因此在程序運行后,這兩個 Bean 都是會被存放到 Spring 中。因為在 UserController 類包含了一個 UserService 對象,并且加了 @Autowired 注解,所以這個 UserService 對象就不需要 new 出來,而是會自動從 Spring 中直接獲取。這就是屬性注入

屬性注入的優點:

? 屬性注入最大的優點就是實現和使用簡單,只需要給變量上添加一個 @Autowired 注解,就可以在不 new 對象的情況下直接獲得注入的對象

屬性注入的缺點:

  1. 無法注入一個不可變的對象,也就是final 修飾的對象
  2. 只能適應于 IoC 容器
  3. 更容易違背單一設計原則

構造方法注入

構造方法注入是在類的構造方法中實現注入

// UserService

@Service
public class UserService {
    public void print(){
        System.out.println("hello");
    }
}
// UserController

@Controller
public class UserController {
   private UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    public void print(){
        userService.print();
    }
}
// Start

public class Start {
    public static void main(String[] args) {
        // 獲取 Spring 的上下文對象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 獲取 Bean 對象
        UserController user = context.getBean("userController", UserController.class);
        // 使用 Bean 對象
        user.print();
    }
}

image-20240126180319147

當該類中只有一個構造方法的時候,可以省略 @Autowired 注解,但是有多個構造方法時就需要在需要注入的方法上加上 @Autowired 注解

構造方法注入的優點:

  1. 可注入不可變對象;
  2. 注入對象不會被修改;(構造方法在對象創建時只會執行一次,因此它不存在注入對象被隨時(調用)修改的情況
  3. 注入對象會被完全初始化;(注入的對象在使用之前會被完全初始化
  4. 通用性更好。(可適用于任何環境,無論是 IoC 框架還是非 IoC 框架

Setter 注入

Setter 注入和屬性的 Setter 方法實現類似,只不過在設置 set 方法的時候需要加上 @Autowired 注解

// UserService

@Service
public class UserService {
    public void print(){
        System.out.println("hello");
    }
}
// UserController

@Controller
public class UserController {
   	private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void print(){
        userService.print();
    }
}
// Start

public class Start {
    public static void main(String[] args) {
        // 獲取 Spring 的上下文對象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 獲取 Bean 對象
        UserController user = context.getBean("userController", UserController.class);
        // 使用 Bean 對象
        user.print();
    }
}

image-20240126180319147

Setter注入的優點:

  1. 完全符合單一職責的設計原則,一個set方法只針對一個對象

Setter注入的缺點:

  1. 不能注入不可變對象;(final 修飾的對象)
  2. 注入的對象可被修改。(因為set方法的緣故,因此對象可以被隨時隨地修改)

@Resource:另?種注入關鍵字

@Controller
public class UserController {
    @Resource
    private UserService userService;

    public void print(){
        userService.print();
    }
}

@Autowired 和 @Resource 的區別:

  1. @Autowired 來自于 Spring,而 @Resource 來自于 JDK 的注解
  2. 相比于 @Autowired 來說,@Resource 支持更多的參數設置,例如 name 設置,根據名稱獲取 Bean,可以使用@Resource(name=“XXX”) 指定獲取。而 @Autowired 需要配合 @Qualifier(value = “XXX”)
  3. @Resource 只能用于 Setter 注入和屬性注入,不能用于構造函數注入

總結

屬性注入的寫法最簡單,所以日常項目中使用的頻率最高,但它的通用性不好;

而 Spring 官方推薦的是構造方法注入,它可以注入不可變對象,其通用性也更好。

如果是注入可變對象,那么可以考慮使用 Setter 注入

原文鏈接:https://blog.csdn.net/CHJBL/article/details/135872582

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新