Spring?@Bean?修飾方法時注入?yún)?shù)的操作方法
一、@Bean 的簡單使用
在開發(fā)中,基于 XML 文件配置 Bean 對象的做法非常繁瑣且不好維護,因此絕大部分情況下都是使用“完全注解開發(fā)”。
對于 Spring 而言,IOC 容器中的 Bean 對象的創(chuàng)建和使用是一大重點,Spring 也為我們提供了注解方式創(chuàng)建 bean 對象:使用 @Bean。
在舉例之前,先熟悉以下兩個需要用到的類:
(1)User 類
package com.demo.pojo; import org.springframework.stereotype.Component; @Component public class User { private String name; public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } }
(2)Book 類
package com.demo.pojo; import org.springframework.stereotype.Component; @Component public class Book { private User user; public void setUser(User user) { this.user = user; } public User getUser() { return user; } }
1、正常情況
(1)下面是一個簡單的 bean 對象創(chuàng)建:
@Bean public User getUser() { return new User(); }
經(jīng)此操作,IOC 中就會多出一個與 <bean id = "getUser" class = "類路徑.User"/> 同義的 bean 對象。即:方法名就是 id,返回類型就是 class。
(2)含有普通類型參數(shù)的 bean 對象創(chuàng)建:
@Bean public User getUser(@Value("wyt") String name) { User user = new User(); user.setName(name); return user; }
需要注意的是,方法中的參數(shù)并不是 bean 對象的成員屬性,而是代表著 bean 對象的創(chuàng)建依賴于這幾個參數(shù),或許用來 setParameter,或許只是中間變量。
而在 xml 文件中的 <property> 則必須要求用 set 方法。
(3)含有對象類型參數(shù)的 bean 對象創(chuàng)建:
package com.demo.config; import com.demo.pojo.Book; import com.demo.pojo.User; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.*; @Configuration public class Config { @Bean public User getUser(@Value("wyt") String name) { User user = new User(); user.setName(name); return user; } @Bean public Book createBook(User user) { Book book = new Book(); book.setUser(user); return book; } }
對比在 xml 中是如何實現(xiàn)參數(shù)是對象類型時的屬性注入:
(4)正常情況下,@Bean 使用總結(jié)
(4-1)@Bean 注解的方法,其返回值就是一個 <bean> 對象,并且注冊到了 IOC 容器中。
- id 為方法的名字;
- class 為方法的返回類型;
(4-2)@Bean 對象的實例化依賴于方法內(nèi)的參數(shù),參數(shù)可以是普通類型,也可以是對象類型。
- 若為普通類型,用 @Value("xxx") 來注入這個參數(shù);
- 若為對象類型,則默認情況下,Spring 會到 IOC 容器中尋找與參數(shù)類型相同的 bean 對象來注入這個參數(shù);
2、問題提出
根據(jù)上述內(nèi)容,我們會想到:如果參數(shù)是對象類型,可是 IOC 中擁有不止一個相同類型的 bean 對象,這該怎么辦呢?
比如下面的情況:
可以看到,Book 對象的參數(shù) user 已經(jīng)報錯了,無法自動裝配,因為存在多個 User 類型的 Bean,Spring 不知道應(yīng)該將哪個 bean 注入到 user 中。
二、解決方案
首先我們要知道,默認情況下,參數(shù)的注入使用的是 @Autowired,不需要顯式寫出。
1、@Qualifier
我們可以想到,@Autowired 是根據(jù)類型自動裝配,當一個類型有多個 bean 對象時失效。
而 @Qualifier 是根據(jù)名稱進行裝配,這不就意味著我們可以用 @Qualifier 來明確需要的 bean 對象嘛。
這有兩種寫法,都是有效的:
- 直接在參數(shù)前加 @Qualifier("function_name");
- 在方法前加 @Qualifier("function_別名"),在參數(shù)前加 @Qualifier("function_別名");
(1)配置類
package com.demo.config; import com.demo.pojo.Book; import com.demo.pojo.User; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.*; @Configuration public class Config { @Bean public User getUser(@Value("wyt") String name) { User user = new User(); user.setName(name); return user; } @Bean public User createUser(@Value("wyt") String name) { User user = new User(); user.setName(name); return user; } @Bean public Book createBook(@Qualifier("createUser") User user) { Book book = new Book(); book.setUser(user); return book; } }
(2)測試代碼
@Test public void SameObjectTest() { ApplicationContext context = new AnnotationConfigApplicationContext(Config.class); Book book = context.getBean("createBook", Book.class); System.out.println(book.getUser()); }
(3)輸出結(jié)果
2、直接寫方法名
因為一般情況下,方法名不能相同,因此也可以通過將參數(shù)名寫成對應(yīng)的方法名來進行注入。
package com.demo.config; import com.demo.pojo.Book; import com.demo.pojo.User; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.*; @Configuration public class Config { @Bean public User getUser(@Value("wyt") String name) { User user = new User(); user.setName(name); return user; } @Bean public User createUser(@Value("wyt") String name) { User user = new User(); user.setName(name); return user; } @Bean public Book createBook(User createUser) { Book book = new Book(); book.setUser(createUser); return book; } }
三、特殊情況
在這里要說明一些特別的對象類型,比如:DataSource。
1、DataSource
(1)問題描述
@Bean public DruidDataSource createDruidDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } @Bean public DruidDataSource getDruidDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; }
當我們像上面的代碼一樣,寫了兩個數(shù)據(jù)源的 bean 對象之后,運行就會出現(xiàn)如下報錯:
No qualifying bean of type 'javax.sql.DataSource' available: expected single matching bean but found 2
簡單來說,就是因為 Spring 有其自身的配置類,導(dǎo)致程序不知道選擇哪一個數(shù)據(jù)源。
(2)解決方法
給其中任意一個加上 @Primary,代表當出現(xiàn)多個同類型 bean 時,優(yōu)先使用哪一個。寫上之后,就可以使用前文所述的方法,如:@Qualifier 或直接寫方法名。
@Bean @Primary public DruidDataSource createDruidDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; }
到此這篇關(guān)于Spring @Bean 修飾方法時如何注入?yún)?shù)的文章就介紹到這了,更多相關(guān)Spring @Bean 注入?yún)?shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java調(diào)用echarts提供的地圖壓縮方法來壓縮地圖
今天小編就為大家分享一篇關(guān)于Java調(diào)用echarts提供的地圖壓縮方法來壓縮地圖,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12springBoot 項目排除數(shù)據(jù)庫啟動方式
這篇文章主要介紹了springBoot 項目排除數(shù)據(jù)庫啟動方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09Eclipse中引入com.sun.image.codec.jpeg包報錯的完美解決辦法
Java開發(fā)中對圖片的操作需要引入 com.sun.image.codec.jpeg,但有時引入這個包會報錯,利用下面的操作可以完成解決這個問題2018-02-02