Bean?掃描
可以瀏覽下面的博客鏈接 :spring 學習 (注解)-CSDN博客
在學習spring 注解時,我們使用 @Component ,@Service,@Controller等 這樣的注解,將目標類信息,傳遞給IOC容器,為其創建對象
那時候掃描,解析為目標類創建對象的注解 有兩者辦法
1 spring 配置文件 中 使用<context :component-scan >標簽 ,在標簽,表明需要掃描哪一個包下的注解,明確 包名。
<context:component-scan base-package="fs">
</context:component-scan>
2 使用注解 掃描
// @Configuration 注解表示當前類是一個配置類,用來代替xml配置文件
@Configuration
// @ComponentScan 注解表示掃描包,用來代替xml配置文件
// basePackages 屬性表示掃描的包
@ComponentScan(basePackages ="fs.exerise")
學習 springBoot 時,發現我們同樣也需要使用很多注解像@Mapper,@RestController,@RequstMapping等...?
思考
1springboot 是spring 家族中的,按理來說也應該存在 掃描注解的。比如@ComponentScan ?
答:在springboot 中確實存在 掃描?,解析的注解。只是被隱藏在 @SpringBootApplication 組成注解中
啟動類
鼠標點擊, @SpringBootApplication 組成注解 按ctrl+b? ,看到 該注解的底層代碼
demo(案例)
驗證 :使用的注解的可以被掃描的范圍是啟動類所在包及其子包
- 啟動類所在包在 springboot01 包下
- 運行截圖
修改:移動 controller 包到 heima 包下和 springboot 01包平級
發現:controller 包掃描不到。因此報了一個404 錯誤 !表示服務器 無法訪問
解決辦法
擴大 掃描范圍,將范圍擴展到heima 包下
運行截圖
總結
1 在springboot 項目中,我們只管寫各自注解 ,至于被使用的注解的掃描,解析過程,將交由springboot 自動完成,不需要我們人為操作。
2 springboot 項目中可以被掃描的范圍是 默認是 啟動類所在包及其子包
Bean 注冊
目的:這里主要研究第三方 jar 對象【非自定義 對象】怎么注入到loc容器
看到這里,我們知道在學習 spring 時使用注解來注冊bean 有:
思考
1 把三方jar 包 bean 對象注入到loc容器 使用這些注解 是否可行呢?
答:
舉例:打開springboot項目的外部庫,任意一個 字節碼文件,都是只讀的。你無法在該類上使用上面說的 bean 注冊的注解。
解決辦法
1 @Bean 注解
功能:將目的對象以方法返回值的形式,傳遞給ioc 容器
@Bean 的使用
1?@Bean 默認方法名就是bean的id 將方法的返回值傳遞給ioc 容器
demo(案例)
目的:使用@ Bean 注解,將Country 對象傳遞給spring 容器
項目準備
1? 使用 黑馬視頻教學使用的第三方jar 包 ,通過網盤分享的文件:02_Bean注冊資料.rar
鏈接: https://pan.baidu.com/s/1rYC0mgIp_eWvdD6h2k015Q 提取碼: mdpv2 解壓 文件
3 打開 本地倉庫文件 修改jar包的所在路徑
4 打開命令行在確保maven 環境配置好的情況下,運行該命令
- 把這個jar 包下載到本地倉庫
5 打開自己的本地倉庫,可以看到 已經下好的jar包
6 打開IDEA 構建springboot 項目,在pom 文件添加已經下載的jar包坐標,最好加載成功
<dependency><groupId>cn.itcast</groupId><artifactId>common-pojo</artifactId><version>1.0</version></dependency>
7 使用@ Bean 注解,將Country ,Provice對象傳遞給spring 容器
正式步驟
1 一個config 包,創建ComonConfig 類作為配置類
package com.it.heima.springboot03.config;import cn.itcast.pojo.Country;
import cn.itcast.pojo.Province;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ComonConfig {@Beanpublic Country getCountry(){return new Country();}@Beanpublic Province getProvince() {return new Province();}
}
2 啟動類中,調用getBean方法,id為默認的方法名
package com.it.heima.springboot03;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication
public class Springboot03Application {public static void main(String[] args) {ApplicationContext run = SpringApplication.run(Springboot03Application.class, args);System.out.println(run.getBean("getCountry"));System.out.println("--------------------------------");System.out.println(run.getBean("getProvince"));}}
3 運行截圖
- 發現 Country 對象,Province 對象已經創建成功
2 @import 注解
使用方式
1 導入配置類
問題: 假設 我們把之前創建的配置類移動到啟動類所在包之外,再一次運行代碼很顯然因為掃描不到配置類,從而無法從ioc容器 獲得 對象,而報錯
解決辦法:在啟動類 使用@import 注解,注解中寫入 配置類的字節碼文件
2 導入ImportSelector 接口實現類
應用場景:如果存在許多 配置類需要導入
- CommonImportSelector 接口實現類
- 啟動類中使用 @Import 注解 ,注解中使用接口實現類的字節碼文件
package com.it.heima.springboot03;import com.it.heima.config.ComonConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;//@Import(ComonConfig.class)
@Import(CommonImportSelector.class)
@SpringBootApplication
public class Springboot03Application {public static void main(String[] args) {ApplicationContext run = SpringApplication.run(Springboot03Application.class, args);System.out.println(run.getBean("getCountry"));System.out.println("--------------------------------");System.out.println(run.getBean("getProvince"));}}
- 運行截圖
更新
在ImportSelector 接口實現類 中把配置類的權限定類名存儲在 配置文件
package com.it.heima.springboot03;import com.it.heima.config.ComonConfig;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;public class CommonImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {InputStream resourceAsStream = CommonImportSelector.class.getClassLoader().getResourceAsStream("config.properties");BufferedReader in = new BufferedReader(new InputStreamReader(resourceAsStream));String line = null;List<String> list = new ArrayList<>();try {while ((line = in.readLine()) != null) {list.add(line);}} catch (Exception e) {e.printStackTrace();}finally {if (in != null){try {in.close();} catch (Exception e) {e.printStackTrace();}}}return list.toArray(new String[0]);}
}
運行截圖
修改啟動類中的 @Import(CommonImportSelector.class),把它試圖變成 組合注解
- 如下圖所示 allCommon組合注解 具備以下三個注解的所有功能
package com.it.heima.springboot03;import org.springframework.context.annotation.Import;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 作用在類上
@Target({ElementType.TYPE})
// 保留到運行時
@Retention(RetentionPolicy.RUNTIME)
@Import(CommonImportSelector.class)
public @interface allCommon {
}
啟動類中
運行截圖