注解@ComponentScan的作用
@Component注解及其衍生注解@RestController、@Controller、@Service和@Repository都是組件注冊注解。@ComponentScan注解主要是從約定的掃描路徑中,識別標注了組件注冊注解的類,並且把這些類自動注冊到spring IoC容器中,這些類就是我們通常所言的bean。IoC容器是Spring的特色之一,可以使用它管理bean。當然,@Configration注解修飾的類也會被托管給IoC容器。
舉個例子,你在微博上@某某,對方會優先看到這條信息,並給你反饋。同理,在Spring中,你標識一個@符號,那么Spring就會關照一下,從你這里拿到一個Bean(自動注冊)或者給出一個Bean(自動裝配)。
思考:Spring怎么知道哪些Java類應該當作bean 注冊到IOC容器中?
解析:使用配置文件或者注解的方式進行標識需要處理的java類,這些被標注的類被Spring識別為bean類。
組件掃描路徑
注解@ComponentScan 如果不設置value屬性,默認掃描路徑是啟動類 XxxApplication.java 所在目錄及其子目錄,所以最好還是配置value屬性,減少加載時間,提高系統啟動速度。
比如啟動類在包 com.eg.wiener 下面,那么項目啟動時,會默認掃描wiener包及其子包下的所有類。也就是說,即便不明確標注@ComponentScan,Spring Boot也會自動搜索當前應用主入口目錄及其下方子目錄。如果其它包中的bean 不在當前主包路徑下面,則應使用@ComponentScan設置value屬性,配置掃描路徑。如果定義了錯誤的掃描路徑,那么在使用注解@Autowired自動裝配Bean時會出錯,報a bean of type that could not be found錯誤。
配置掃描路徑
@ComponentScan注解既可以掃描包,也可以掃描指定的類。我們只需要指定一個需要掃描的路徑,就可以達到更改掃描路徑的目的。
- 包路徑
通過value屬性設置需要掃描的包:
@ComponentScan({"com.company.user","com.company.service"})
- 類路徑
通過basePackageClasses屬性指定需要掃描的類:
@ComponentScan(basePackageClasses={XxxService.class, YyyService.class})
@Component和@ComponentScan的區別
@Component和@ComponentScan有什么區別?二者用於不同目的,咱們結合學生搶答老師的問題這一場景來解釋。@Component表示哪些類可能是bean的候選者,就像哪些同學舉手搶答問題一樣。@ComponentScan 搜索組件包中的類,找到所有bean的候選者,就像老師試圖找出哪些同學舉手搶答問題。通俗一點解釋,就是全班同學代表掃描路徑下的所有類,搶答者就是被@Component注解修飾的類,而找到所有搶答者的老師就是@ComponentScan。延伸一點,成功搶到答題機會的同學就是被@Autowire裝配的bean了。
注解@ComponentScan實現原理
本節介紹 Spring Boot 中注解 @ComponentScan 的實現原理。
下面介紹一下ComponentScan注解中幾個常用的屬性。
- String[] value() default {};
指定包掃描路徑,value屬性的值,就是項目中的一個具體路徑。value屬性的類型是String數組,也就是支持一次指定多個包掃描路徑。這個屬性上面添加了一個注解,@AliasFor("basePackages"),這個注解的意思就是說,value這個屬性等價於basePackages屬性。關於basePackages屬性,下面會講到。 - Class<?>[] basePackagesClasses() default {};
掃描具體的類。basePackagesClasses屬性的類型是Class數組,也就是說支持同時指定多個掃描類。 - Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator. class;
配置beanName生成器,默認是BeanNameGenerator。一般情況下,我們都是使用默認的beanName生成器,但是Spring實現了beanName生成器的可配置。 - boolean useDefaultFilters() default true;
是否對含有以下注解的類開啟檢測,默認是開啟的。
@Component
@Repository
@Service
@Controller - ComponentScan.Filter[] includeFilters() default {};
指定某些Filter掃描到的類。聽起來有些費勁,說白了就是指定了類型,掃描指定的這些類型。可選類型有5種,定義在枚舉類FilterType中:
第一種:ANNOTATION
第二種:ASSIGNABLE_TYPE
第三種:ASPECTJ
第四種:REGEX,正則表達式。
第五種:CUSTOM,自定義類型。 - ComponentScan.Filter[] excludeFilters() default {};
排除過濾器掃描的的類。