Java開發學習(十三)----基於註解開發定義第三方bean及註解開發總結

2022-07-18 21:00:24

在前面的部落格中定義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設定和註解的開發實現,至於兩者之間的差異,咱們放在一塊去對比回顧下: