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

Spring使用注解進(jìn)行對(duì)象注入的示例詳解

 更新時(shí)間:2023年07月26日 15:18:53   作者:韻秋梧桐  
獲取?Bean?對(duì)象也叫做對(duì)象裝配,就是把對(duì)象取出來(lái)放到某個(gè)類(lèi)中,有時(shí)候也叫對(duì)象注入,常見(jiàn)有關(guān)對(duì)象注入的注解有兩個(gè),一個(gè)是@Autowired,另外一個(gè)是@Resource,下面就來(lái)講講它們的具體使用吧

一. 什么是對(duì)象裝配

獲取 Bean 對(duì)象也叫做對(duì)象裝配,就是把對(duì)象取出來(lái)放到某個(gè)類(lèi)中,有時(shí)候也叫對(duì)象注入。

對(duì)象裝配(對(duì)象注入)的實(shí)現(xiàn)方法以下 3 種:

  • 屬性注入 ,就是將對(duì)象注入到某個(gè)類(lèi)的一個(gè)屬性當(dāng)中。
  • 構(gòu)造方法注入 ,就是通過(guò)構(gòu)造方法來(lái)將對(duì)象注入到類(lèi)中。
  • Setter 注入 ,通過(guò) SetXXX 系列方法將對(duì)象注入到類(lèi)中。

常見(jiàn)有關(guān)對(duì)象注入的注解有兩個(gè),一個(gè)是@Autowired,另外一個(gè)是@Resource

它們兩者的區(qū)別如下:

1.出身不同:@Autowired 是由Spring提供的,而 @Resource 是JDK提供的。

2.查找順序不同:從容器中獲取對(duì)象時(shí) @Autowired 先根據(jù)類(lèi)型再根據(jù)名稱(chēng)查詢(xún),而 @Resource 先根據(jù)名稱(chēng)再根據(jù)類(lèi)型查詢(xún)。

3.使?時(shí)設(shè)置的參數(shù)不同:@Resource 支持更多的參數(shù)設(shè)置(有 7 個(gè)),如name、type等,而@Autowired只支持設(shè)置required一個(gè)參數(shù),用來(lái)設(shè)置注入 Bean 的時(shí)候該 Bean 是否必須存在(true/false)。

4.依賴(lài)注入支持不同:@Autowired 支持屬性注入,構(gòu)造方法注入和 Setter 注入,而 @Resource 只支持屬性注入和 Settter 注入,但是不支持構(gòu)造方法注入。

5.對(duì) IDEA 的兼容性支持不同:使用 @Autowired 在 IDEA 旗艦版下可能會(huì)有誤報(bào)(設(shè)置required即可);而 @Resource 不存在誤報(bào)的問(wèn)題。

二. 三種注入方式

1. 屬性注入

屬性注入只需要在需要注入對(duì)象的屬性上加上 @Autowired 或者 @Resource 注解就可以了,這里以 @Autowired 為例。

首先來(lái)看第一種情況,待注入的同類(lèi)對(duì)象只有一個(gè),此時(shí)我們直接使用 @Autowired 注解就好,不必設(shè)置參數(shù),例如我們?cè)?code>UserController類(lèi)里面注入UserService對(duì)象。

下面UserService的結(jié)構(gòu),先使用 @Service 將 Bean 存放到 Spring 中:

package com.tr.demo.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
    public void sayHi() {
        System.out.println("Hello, UserService~");
    }
}

屬性注入:

package com.tr.demo.controller;
import com.tr.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
    //屬性注入
    @Autowired
    private UserService userService;
    public void sayHi() {
        userService.sayHi();
    }
}

此時(shí)我們就可以在啟動(dòng)類(lèi)中,使用上下文對(duì)象來(lái)獲取到UserController對(duì)象,通過(guò)執(zhí)行UserController對(duì)象的sayHi方法來(lái)進(jìn)而調(diào)用到注入的UserService對(duì)象中的sayHi方法了,此時(shí)的UserService對(duì)象就不是我們自己new出來(lái)的了。

import com.tr.demo.controller.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");
        UserController usercontroller =  context.getBean("userController", UserController.class);
        usercontroller.sayHi();
    }
}

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

上面說(shuō)的是同類(lèi)對(duì)象只有一個(gè)的情況,而如果存在多個(gè)同類(lèi)對(duì)象,我們就得通過(guò)參數(shù)來(lái)告知容器我們要注入哪一個(gè)對(duì)象,不告知就會(huì)報(bào)錯(cuò)。

比如我們將多個(gè)User對(duì)象添加到容器中,如下:

package com.tr.demo.model;
// User 結(jié)構(gòu)
public class User {
    private int id;
    private String name;
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
package com.tr.demo.model;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class UserBeans {
    // 使用方法注解添加多個(gè) User 對(duì)象到容器中
    @Bean("user1")
    public User user1(){
        User user = new User();
        user.setId(1);
        user.setName("張三");
        return user;
    }
    @Bean("user2")
    public User user2(){
        User user = new User();
        user.setId(2);
        user.setName("李四");
        return user;
    }
    @Bean("user3")
    public User user3(){
        User user = new User();
        user.setId(3);
        user.setName("王五");
        return user;
    }
}

而在UserController2類(lèi)中需要注入User對(duì)象,此時(shí)我們運(yùn)行程序就會(huì)報(bào)錯(cuò):

package com.tr.demo.controller;
import com.tr.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController2 {
    @Autowired
    private User user;
    public void sayHi() {
        System.out.println("Hello, " + user);
    }
}

我們?cè)囍酝瑯拥姆椒▉?lái)調(diào)用sayHi方法:

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

@Autowired 依賴(lài)注入流程首先是先根據(jù)類(lèi)型從容器中獲取對(duì)象,如果只能獲取到一個(gè),那么就直接將此對(duì)象注入到當(dāng)前屬性上;如果能獲取到多個(gè)對(duì)象,此時(shí)會(huì)使用 BeanName 進(jìn)行匹配,而我們添加到 Spring 中的對(duì)象是沒(méi)有一個(gè)叫user的,所以程序就報(bào)錯(cuò)了。

此時(shí)就需要我們來(lái)告知容器我們需要哪一個(gè)具體的 Bean,要獲得目標(biāo)對(duì)象主要有下面三種方法:

方法1:將屬性的變量名設(shè)置為你需要的那個(gè)BeanName就可以了,后面的構(gòu)造方法與 Setter 注入同理,將形參名設(shè)置成與BeanName相同即可。

方法2:@Autowired 注解與 @Qualifier 注解配合使用,設(shè)置 @Qualifier 的value參數(shù)為BeanName即可,要注意 @Qualifier 注解不能修飾方法,只能修飾變量。

方法3:將 @Autowired 注解替換成 @Resource 注解的,并將它name參數(shù)值設(shè)置為BeanName即可。

2. 構(gòu)造方法注入

在構(gòu)造方法加上 @Autowired 注解就可,要注意 @Resource 注解是不支持構(gòu)造方法注入的,我們就直接演示如何獲取取多個(gè)同類(lèi)對(duì)象中的其中一個(gè)了,還是用上面添加到容器中的多個(gè) User 對(duì)象。

方法1:將構(gòu)造方法形參名設(shè)置為user1

package com.tr.demo.controller;
import com.tr.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController3 {
    private User user;
    @Autowired
    public UserController3(User user1) {
        this.user = user1;
    }
    public void sayHi() {
        System.out.println("Hello, " + user);
    }
}

啟動(dòng)類(lèi)就不貼代碼了,一樣的,運(yùn)行結(jié)果如下:

方法2:@Autowired 搭配 @Qualifier

package com.tr.demo.controller;
import com.tr.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
@Controller
public class UserController4 {
    private User user;
    @Autowired
    public UserController4(@Qualifier(value = "user2") User user) {
        this.user = user;
    }
    public void sayHi() {
        System.out.println("Hello, " + user);
    }
}

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

對(duì)了,如果一個(gè)類(lèi)中只有一個(gè)構(gòu)造方法,@Autowired 是可以省略的,演示一下:

package com.tr.demo.controller;
import com.tr.demo.model.User;
import org.springframework.stereotype.Controller;
@Controller
public class UserController5 {
    private User user;
    public UserController5(User user3) {
        this.user = user3;
    }
    public void sayHi() {
        System.out.println("Hello, " + user);
    }
}

此時(shí)仍然是可以成功注入對(duì)象。

如果有多個(gè)構(gòu)造方法,要注意此時(shí)是不能省略 @Autowired 的,會(huì)導(dǎo)致會(huì)注入對(duì)象失敗。

package com.tr.demo.controller;
import com.tr.demo.model.User;
import org.springframework.stereotype.Controller;
@Controller
public class UserController6 {
    private User user;
    public UserController6(User user1) {
        this.user = user1;
    }
    public UserController6() {
        System.out.println("調(diào)用無(wú)參構(gòu)造");
    }
    public void sayHi() {
        System.out.println("Hello, " + user);
    }
}

此時(shí)可以看到注入對(duì)象失敗了,輸出的結(jié)果是null

當(dāng)然此時(shí)加上 @Autowired 注解就能正常注入了,就不做展示了。

3. Setter注入

Setter 注入就是在 setXXX 系列方法上加上 @Resource 或者 @Autowired 進(jìn)行注入,和構(gòu)造方法注入大同小異,簡(jiǎn)單演示一下。

package com.tr.demo.controller;
import com.tr.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
@Controller
public class UserController7 {
    private User user;
    @Autowired
    public void setUser(@Qualifier(value = "user2") User user) {
        this.user = user;
    }
    public void sayHi() {
        System.out.println("Hello, " + user);
    }
}

啟動(dòng)類(lèi)和運(yùn)行結(jié)果:

這里這里第一行輸入的是因?yàn)閱?dòng)程序會(huì)將上面寫(xiě)的UserController6也添加到容器中,UserController6的無(wú)參構(gòu)造方法是我們自定義的。

三. 三種注入方式的優(yōu)缺點(diǎn)

在早期的 Spring 版本中,官方推薦使用的 Setter 注入,最開(kāi)始說(shuō)的原因就是不符合單一設(shè)計(jì)原則吧,而現(xiàn)在比較新的 Spring 版本(Sring 4.x 之后)中,官方最使用推薦的又是構(gòu)造方法注入了,說(shuō)法是因?yàn)樗耐ㄓ眯宰詈谩?/p>

屬性注入

優(yōu)點(diǎn):

使用起來(lái)簡(jiǎn)單方便

缺點(diǎn):

1.無(wú)法注入到一個(gè)final修飾的變量,因?yàn)?final 修飾的變量只有兩種賦值方式,一是直接賦值,二是通過(guò)構(gòu)造方法進(jìn)行賦值,而屬性注入這兩種方式都不能滿(mǎn)足。

2.通用性問(wèn)題,屬性注入只能在 IoC 容器中使用,在非 IoC 容器中是不可?的。

3.更容易違背單一設(shè)計(jì)原則,簡(jiǎn)單理解就是注入方式越簡(jiǎn)單,濫用的概率越大,就比如在數(shù)據(jù)持久層有一個(gè)針對(duì)用戶(hù)操作的類(lèi),本來(lái)這個(gè)類(lèi)就只是注入用戶(hù)相關(guān)操作的依賴(lài)就行了,但由于屬性注入使用起來(lái)成本不高,程序猿就多注了一些依賴(lài)去完成了一些和用戶(hù)操作無(wú)關(guān)的內(nèi)容,這就違背了單一設(shè)計(jì)原則了。

Setter 注入

優(yōu)點(diǎn):

通常情況下,setXXX 系列的方法中只會(huì)設(shè)置一個(gè)屬性,就更符合單一設(shè)計(jì)原則。

缺點(diǎn):

1.同樣的,也不能注入到一個(gè) final 修飾的變量中。

2.注入的對(duì)象是可能被修改的,因?yàn)?setXXX 系列的方法隨時(shí)都有可能被調(diào)用導(dǎo)致注入的 Bean 就被修改了。

構(gòu)造方法注入

優(yōu)點(diǎn):

1.可以注入到一個(gè)被 final 修飾的變量。

2.注入對(duì)象不會(huì)被修改,因?yàn)闃?gòu)造方法只會(huì)在對(duì)象創(chuàng)建時(shí)執(zhí)行一次,不存在注入對(duì)象被隨時(shí)修改的情況。

3.可以保證注入對(duì)象的完全初始化,因?yàn)闃?gòu)造方法是在對(duì)象創(chuàng)建之前執(zhí)行的。

4.通用性最好,因?yàn)椴还苣阍趺磳?xiě) Java 代碼,創(chuàng)建實(shí)例對(duì)象時(shí)都要執(zhí)行構(gòu)造方法吧。

缺點(diǎn):

1.相較于屬性注入,寫(xiě)法更加復(fù)雜,如果有多個(gè)注?會(huì)顯得?較臃腫,但出現(xiàn)這種情況你應(yīng)該考慮?下當(dāng)前類(lèi)是否符合程序的單?職責(zé)的設(shè)計(jì)模式了。

2.使用構(gòu)造注入,無(wú)法解決循環(huán)依賴(lài)的問(wèn)題。

四. 綜合練習(xí)

在 Spring 項(xiàng)?中,通過(guò) main ?法獲取到 Controller 類(lèi),調(diào)? Controller ??通過(guò)注?的?式調(diào)? Service 類(lèi),Service 再通過(guò)注?的?式獲取到 Repository 類(lèi),Repository 類(lèi)??有?個(gè)?法構(gòu)建? 個(gè) User 對(duì)象,返回給 main ?法。Repository ?需連接數(shù)據(jù)庫(kù),使?偽代碼即可。

首先要清楚的是在 main 方法中是不能使用依賴(lài)注入的,因?yàn)轭?lèi)的靜態(tài)部分是在 Spring 注入之前的加載的,仔細(xì)想一下,在類(lèi)加載時(shí)就要使用一個(gè)還沒(méi)注入的對(duì)象這是不現(xiàn)實(shí)的。

所以我們要在 main 中執(zhí)行的是將掃描路徑中的類(lèi)添加到 Spring 中,對(duì)象的注入要在 mian 方法所在類(lèi)的外部去實(shí)現(xiàn)。

package com.tr.demo.model;
public class User {
    private int id;
    private String name;
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
package com.tr.demo.repository;
import com.tr.demo.model.User;
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository {
    public User getUser(){
        // 偽代碼
        User user = new User();
        user.setId(1);
        user.setName("張三");
        return user;
    }
}
package com.tr.demo.service;
import com.tr.demo.model.User;
import com.tr.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    public User getUser(){
        return userRepository.getUser();
    }
}
package com.tr.demo.contoller;
import com.tr.demo.model.User;
import com.tr.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public User getUser(){
        return userService.getUser();
    }
}
package com.tr.demo;
import com.tr.demo.contoller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * 啟動(dòng)類(lèi)
 */
public class App {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        UserController userController =
                context.getBean("userController", UserController.class);
        System.out.println(userController.getUser());
    }
}

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

到此這篇關(guān)于Spring使用注解進(jìn)行對(duì)象注入的示例詳解的文章就介紹到這了,更多相關(guān)Spring對(duì)象注入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring中@Configuration和@Component注解的區(qū)別及原理

    Spring中@Configuration和@Component注解的區(qū)別及原理

    這篇文章主要介紹了Spring中@Configuration和@Component注解的區(qū)別及原理,從功能上來(lái)講,這些注解所負(fù)責(zé)的功能的確不相同,但是從本質(zhì)上來(lái)講,Spring內(nèi)部都將其作為配置注解進(jìn)行處理,需要的朋友可以參考下
    2023-11-11
  • SpringBoot實(shí)現(xiàn)阿里云快遞物流查詢(xún)的示例代碼

    SpringBoot實(shí)現(xiàn)阿里云快遞物流查詢(xún)的示例代碼

    本文將基于springboot實(shí)現(xiàn)快遞物流查詢(xún),物流信息的獲取通過(guò)阿里云第三方實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-10-10
  • java foreach循環(huán)為什么不能賦值的講解

    java foreach循環(huán)為什么不能賦值的講解

    這篇文章主要介紹了java foreach循環(huán)為什么不能賦值的講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 詳解Java如何實(shí)現(xiàn)一個(gè)像String一樣不可變的類(lèi)

    詳解Java如何實(shí)現(xiàn)一個(gè)像String一樣不可變的類(lèi)

    說(shuō)到?String?大家都知道?String?是一個(gè)不可變的類(lèi);雖然用的很多,那不知道小伙伴們有沒(méi)有想過(guò)怎么樣創(chuàng)建一個(gè)自己的不可變的類(lèi)呢?這篇文章就帶大家來(lái)實(shí)踐一下,創(chuàng)建一個(gè)自己的不可變的類(lèi)
    2022-11-11
  • SpringBoot中集成串口通信的項(xiàng)目實(shí)踐

    SpringBoot中集成串口通信的項(xiàng)目實(shí)踐

    本文主要介紹了SpringBoot中集成串口通信,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • SpringMVC實(shí)現(xiàn)全局異常處理器的經(jīng)典案例

    SpringMVC實(shí)現(xiàn)全局異常處理器的經(jīng)典案例

    文章介紹了如何使用@ControllerAdvice和相關(guān)注解實(shí)現(xiàn)SpringMVC的全局異常處理,通過(guò)統(tǒng)一的異常處理類(lèi)和自定義業(yè)務(wù)異常類(lèi),可以將所有控制器的異常集中處理,并以JSON格式返回給前端,感興趣的朋友一起看看吧
    2025-03-03
  • spring入門(mén)教程之bean的繼承與自動(dòng)裝配詳解

    spring入門(mén)教程之bean的繼承與自動(dòng)裝配詳解

    眾所周知Spring里面的bean就類(lèi)似是定義的一個(gè)組件,而這個(gè)組件的作用就是實(shí)現(xiàn)某個(gè)功能的,下面這篇文章主要給大家介紹了關(guān)于spring入門(mén)教程之bean繼承與自動(dòng)裝配的相關(guān)資料,需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • springboot使用redis的詳細(xì)步驟

    springboot使用redis的詳細(xì)步驟

    SpringBoot對(duì)常用的數(shù)據(jù)庫(kù)支持外,對(duì)NoSQL?數(shù)據(jù)庫(kù)也進(jìn)行了封裝自動(dòng)化,下面這篇文章主要給大家介紹了關(guān)于springboot使用redis的詳細(xì)步驟,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • 基于Java實(shí)現(xiàn)修改圖片分辨率示例代碼

    基于Java實(shí)現(xiàn)修改圖片分辨率示例代碼

    這篇文章主要介紹了一個(gè)可以修改圖片分辨率的java工具類(lèi),文中的示例代碼講解詳細(xì),對(duì)學(xué)習(xí)JAVA有一定的幫助,感興趣的小伙伴快來(lái)跟隨小編一起學(xué)習(xí)吧
    2021-12-12
  • springboot 自定義異常并捕獲異常返給前端的實(shí)現(xiàn)代碼

    springboot 自定義異常并捕獲異常返給前端的實(shí)現(xiàn)代碼

    在開(kāi)發(fā)中,如果用try catch的方式,每個(gè)方法都需要單獨(dú)實(shí)現(xiàn),為了方便分類(lèi)異常,返回給前端,采用了@ControllerAdvice注解和繼承了RuntimeException的方式來(lái)實(shí)現(xiàn),具體實(shí)現(xiàn)內(nèi)容跟隨小編一起看看吧
    2021-11-11

最新評(píng)論

原平市| 新津县| 沽源县| 湘潭县| 岱山县| 崇阳县| 丹寨县| 报价| 建德市| 项城市| 沙雅县| 全椒县| 小金县| 措勤县| 迁西县| 同仁县| 霸州市| 喀喇沁旗| 鲁山县| 杭锦后旗| 金华市| 集贤县| 迭部县| 弥渡县| 霍邱县| 革吉县| 扬州市| 青海省| 安达市| 淳化县| 洮南市| 营山县| 历史| 孟津县| 沐川县| 浦东新区| 溆浦县| 东丽区| 高安市| 保亭| 从江县|