在前面的部落格中定義bean的時候都是在自己開發的類上面寫個註解就完成了,但如果是第三方的類,這些類都是在jar包中,我們沒有辦法在類上面新增註解,這個時候該怎麼辦?
遇到上述問題,我們就需要有一種更加靈活的方式來定義bean,這種方式不能在原始程式碼上面書寫註解,一樣能定義bean,這就用到了一個全新的註解@Bean。
這個註解該如何使用呢?
一、環境準備
學習@Bean註解之前先來準備環境:
-
建立一個Maven專案
-
pom.xml新增Spring的依賴
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.10.RELEASE</version> </dependency> </dependencies>
-
新增一個配置類
SpringConfig
@Configuration public class SpringConfig { }
-
新增BookDao、BookDaoImpl類
public interface BookDao { public void save(); } @Repository public class BookDaoImpl implements BookDao { public void save() { System.out.println("book dao save ..." ); } }
-
建立執行類App
public class App { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); } }
最終建立好的專案結構如下:
二、註解開發管理第三方bean
在上述環境中完成對Druid
資料來源的管理,具體的實現步驟為:
步驟1:匯入對應的jar包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
步驟2:在配置類中新增一個方法
注意該方法的返回值就是要建立的Bean物件型別
@Configuration
public class SpringConfig {
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
步驟3:在方法上新增@Bean
註解
@Bean註解的作用是將方法的返回值製作為Spring管理的一個bean物件
@Configuration
public class SpringConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
注意:不能使用DataSource ds = new DruidDataSource()
因為DataSource介面中沒有對應的setter方法來設定屬性。
步驟4:從IOC容器中獲取物件並列印
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println(dataSource);
}
}
至此使用@Bean來管理第三方bean的案例就已經完成。如果有多個bean要被Spring管理,直接在配置類中多些幾個方法,方法上新增@Bean註解即可。
三、引入外部配置類
如果把所有的第三方bean都配置到Spring的配置類SpringConfig
中,雖然可以,但是不利於程式碼閱讀和分類管理,所有我們就想能不能按照類別將這些bean配置到不同的配置類中?
對於資料來源的bean,我們新建一個JdbcConfig
配置類,並把資料來源配置到該類下。
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
現在的問題是,這個配置類如何能被Spring配置類載入到,並建立DataSource物件在IOC容器中?針對這個問題,有兩個解決方案:
3.1 使用包掃描引入
步驟1:在Spring的配置類上新增包掃描
@Configuration
@ComponentScan("com.itheima.config")
public class SpringConfig {
}
步驟2:在JdbcConfig上新增配置註解
JdbcConfig類要放入到com.itheima.config
包下,需要被Spring的配置類掃描到即可
@Configuration
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
步驟3:執行程式
依然能獲取到bean物件並列印控制檯。這種方式雖然能夠掃描到,但是不能很快的知曉都引入了哪些配置類,所有這種方式不推薦使用。
3.2 使用@Import
引入
方案一實現起來有點小複雜,Spring早就想到了這一點,於是又給我們提供了第二種方案。
這種方案可以不用加@Configuration
註解,但是必須在Spring配置類上使用@Import
註解手動引入需要載入的配置類
步驟1:去除JdbcConfig類上的註解
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
步驟2:在Spring配置類中引入
@Configuration
//@ComponentScan("com.itheima.config")
@Import({JdbcConfig.class})
public class SpringConfig {
}
注意:
-
掃描註解可以移除
-
@Import引數需要的是一個陣列,可以引入多個配置類。
-
@Import註解在配置類中只能寫一次,下面的方式是不允許的
@Configuration //@ComponentScan("com.itheima.config") @Import(JdbcConfig.class) @Import(Xxx.class) public class SpringConfig { }
步驟3:執行程式
依然能獲取到bean物件並列印控制檯
知識點1:@Bean
名稱 | @Bean |
---|---|
型別 | 方法註解 |
位置 | 方法定義上方 |
作用 | 設定該方法的返回值作為spring管理的bean |
屬性 | value(預設):定義bean的id |
知識點2:@Import
名稱 | @Import |
---|---|
型別 | 類註解 |
位置 | 類定義上方 |
作用 | 匯入配置類 |
屬性 | value(預設):定義匯入的配置類類名, 當配置類有多個時使用陣列格式一次性匯入多個配置類 |
四、註解開發實現為第三方bean注入資源
在使用@Bean建立bean物件的時候,如果方法在建立的過程中需要其他資源該怎麼辦?
這些資源會有兩大類,分別是簡單資料型別
和引用資料型別
。
4.1 簡單資料型別
4.1.1 需求分析
對於下面程式碼關於資料庫的四要素不應該寫死在程式碼中,應該是從properties配置檔案中讀取。如何來優化下面的程式碼?
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
4.1.2 注入簡單資料型別步驟
步驟1:類中提供四個屬性
public class JdbcConfig {
private String driver;
private String url;
private String userName;
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
步驟2:使用@Value
註解引入值
public class JdbcConfig {
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("jdbc:mysql://localhost:3306/spring_db")
private String url;
@Value("root")
private String userName;
@Value("password")
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
}
擴充套件
現在的資料庫連線四要素還是寫在程式碼中,需要做的是將這些內容提
取到jdbc.properties配置檔案,具體實現步驟如下:
1.resources目錄下新增jdbc.properties
2.配置檔案中提供四個鍵值對分別是資料庫的四要素
3.使用@PropertySource載入jdbc.properties配置檔案
4.修改@Value註解屬性的值,將其修改為
${key}
,key就是鍵值對中的鍵的值
具體的實現這裡就不實現了,可以參考前面的部落格。
4.2 引用資料型別
4.2.1 需求分析
假設在構建DataSource物件的時候,需要用到BookDao物件,該如何把BookDao物件注入進方法內讓其使用呢?
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
4.2.2 注入引用資料型別步驟
步驟1:在SpringConfig中掃描BookDao
掃描的目的是讓Spring能管理到BookDao,也就是說要讓IOC容器中有一個bookDao物件
@Configuration
@ComponentScan("com.itheima.dao")
@Import({JdbcConfig.class})
public class SpringConfig {
}
步驟2:在JdbcConfig類的方法上新增引數
@Bean
public DataSource dataSource(BookDao bookDao){
System.out.println(bookDao);
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
引用型別注入只需要為bean定義方法設定形參即可,容器會根據型別自動裝配物件。
步驟3:執行程式
五、註解開發總結
在前面的部落格中我們已經完成了XML配置和註解的開發實現,至於兩者之間的差異,我們們放在一塊去對比回顧下: