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

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