在前面的部落格中定義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);
}
}
最終建立好的專案結構如下:
在上述環境中完成對Druid
資料來源的管理,具體的實現步驟為:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
注意該方法的返回值就是要建立的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;
}
}
@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方法來設定屬性。
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容器中?針對這個問題,有兩個解決方案:
@Configuration
@ComponentScan("com.itheima.config")
public class SpringConfig {
}
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;
}
}
依然能獲取到bean物件並列印控制檯。這種方式雖然能夠掃描到,但是不能很快的知曉都引入了哪些設定類,所有這種方式不推薦使用。
@Import
引入方案一實現起來有點小複雜,Spring早就想到了這一點,於是又給我們提供了第二種方案。
這種方案可以不用加@Configuration
註解,但是必須在Spring設定類上使用@Import
註解手動引入需要載入的設定類
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;
}
}
@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 {
}
依然能獲取到bean物件並列印控制檯
名稱 | @Bean |
---|---|
型別 | 方法註解 |
位置 | 方法定義上方 |
作用 | 設定該方法的返回值作為spring管理的bean |
屬性 | value(預設):定義bean的id |
名稱 | @Import |
---|---|
型別 | 類註解 |
位置 | 類定義上方 |
作用 | 匯入設定類 |
屬性 | value(預設):定義匯入的設定類類名, 當設定類有多個時使用陣列格式一次性匯入多個設定類 |
在使用@Bean建立bean物件的時候,如果方法在建立的過程中需要其他資源該怎麼辦?
這些資源會有兩大類,分別是簡單資料型別
和參照資料型別
。
對於下面程式碼關於資料庫的四要素不應該寫死在程式碼中,應該是從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;
}
}
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;
}
}
@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就是鍵值對中的鍵的值
具體的實現這裡就不實現了,可以參考前面的部落格。
假設在構建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;
}
}
掃描的目的是讓Spring能管理到BookDao,也就是說要讓IOC容器中有一個bookDao物件
@Configuration
@ComponentScan("com.itheima.dao")
@Import({JdbcConfig.class})
public class SpringConfig {
}
@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定義方法設定形參即可,容器會根據型別自動裝配物件。
在前面的部落格中我們已經完成了XML設定和註解的開發實現,至於兩者之間的差異,咱們放在一塊去對比回顧下:
本文來自部落格園,作者:|舊市拾荒|,轉載請註明原文連結:https://www.cnblogs.com/xiaoyh/p/16324442.html