Spring?component-scan?XML配置與@ComponentScan注解配置
前言
無(wú)論Spring的XML配置或者Java配置,都可以配置自動(dòng)掃描,也就是在指定包及其子包下的component,都會(huì)被自動(dòng)掃描并被Spring容器管理。
注:component指的是被 @Component
注解及其變種(如 @Controller
、 @Service
、 @Repository
、 @Configuration
等)所修飾的類(lèi)。
環(huán)境:
- Ubuntu 22.04
- IntelliJ IDEA 2022.1.3
- JDK 17.0.3
- Spring 5.3.21
準(zhǔn)備
創(chuàng)建Maven項(xiàng)目 test0831
。
修改 pom.xml
文件,添加依賴(lài):
...... <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.21</version> </dependency> ......
在 src/test/java
目錄下創(chuàng)建測(cè)試:
public class MyTest {}
創(chuàng)建如下POJO:
Axe
:Axe接口;StoneAxe
:Axe實(shí)現(xiàn)類(lèi);SteelAxe
:Axe實(shí)現(xiàn)類(lèi);Person
:Person持有Axe
package pojo; public interface Axe { public void chop(); }
package pojo; import org.springframework.stereotype.Component; @Component public class StoneAxe implements Axe{ @Override public void chop() { System.out.println("Stone axe!"); } }
package pojo; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @Component @Primary public class SteelAxe implements Axe{ @Override public void chop() { System.out.println("Steel axe!"); } }
package pojo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class Person { private String name; private Axe axe; public void setAxe(Axe axe) { this.axe = axe; } public void setName(String name) { this.name = name; } public void useAxe() { System.out.println("I am " + name); axe.chop(); } @Autowired public Person(@Value("Tom") String name, Axe axe) { this.name = name; this.axe = axe; } }
注:本例使用了 @Autowired
注解來(lái)自動(dòng)裝配注入,默認(rèn)是 byType
,當(dāng)有多個(gè)類(lèi)都滿(mǎn)足條件時(shí)Spring會(huì)報(bào)錯(cuò),所以使用了 @Primary
注解來(lái)指定優(yōu)先選擇該類(lèi)。
@Component的bean
XML配置
配置:
在 src/main/resources
目錄下創(chuàng)建 applicationContext.xml
文件:
<?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="pojo"/> </beans>
測(cè)試:
創(chuàng)建測(cè)試如下:
@Test public void test1() { var ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); var person = ctx.getBean("person", Person.class); person.useAxe(); }
運(yùn)行測(cè)試,結(jié)果如下:
I am Tom
Steel axe!
Java配置 配置
創(chuàng)建Java配置類(lèi) MyConfig.java
如下:
package config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(basePackages = {"pojo"}) public class MyConfig { }
測(cè)試:
創(chuàng)建測(cè)試如下:
@Test public void test2() { var ctx = new AnnotationConfigApplicationContext(MyConfig.class); var person = ctx.getBean("person", Person.class); person.useAxe(); }
運(yùn)行測(cè)試,結(jié)果如下:
I am Tom
Steel axe!
@Configuration的bean
自動(dòng)掃描時(shí),如果遇到Java配置類(lèi),也會(huì)加載其配置。
在 pojo
包下添加Java配置類(lèi) MyConfig2
:
package pojo; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyConfig2 { @Bean public String xxx() { return "xxx"; } }
本例中, MyConfig2
是一個(gè)配置類(lèi),其中配置了ID為 xxx
的bean。
XML配置 配置
前面已經(jīng)配置了:
<context:component-scan base-package="pojo"/>
MyConfig2
在 pojo
包下,所以無(wú)需額外的配置。
測(cè)試
創(chuàng)建測(cè)試如下:
@Test public void test3() { var ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); var xxx = ctx.getBean("xxx", String.class); System.out.println(xxx); }
運(yùn)行測(cè)試,結(jié)果如下:
xxx
Java配置 配置
前面已經(jīng)配置了:
@ComponentScan(basePackages = {"pojo"})
MyConfig2
在 pojo
包下,所以無(wú)需額外的配置。
測(cè)試
創(chuàng)建測(cè)試如下:
@Test public void test4() { var ctx = new AnnotationConfigApplicationContext(MyConfig.class); var xxx = ctx.getBean("xxx", String.class); System.out.println(xxx); }
運(yùn)行測(cè)試,結(jié)果如下:
xxx
小結(jié)
@Configuration
是 @Component
的變種,因此也會(huì)被自動(dòng)掃描并加載。
如果Java配置類(lèi)不是在自動(dòng)掃描的路徑里,則需要顯式加載:
通過(guò)XML配置加載:
<context:annotation-config/> <bean class="config.MyConfig3"/>
通過(guò)Java配置加載:
@Import({MyConfig3.class})
總結(jié)
- 在類(lèi)上添加
@Component
(或者其變種)注解。 - 配置自動(dòng)掃描,以下兩種方式都可以:
XML配置:
<context:component-scan base-package="pojo"/>
Java配置:
@Configuration @ComponentScan(basePackages = {"pojo"}) public class MyConfig { }
對(duì)于自動(dòng)掃描路徑里面的Java配置類(lèi)( @Configuration
注解所修飾的類(lèi)),也會(huì)被加載生效。
注:關(guān)于Spring的XML配置和Java配置,詳見(jiàn)我另一篇文檔 https://blog.csdn.net/duke_ding2/article/details/125605817
。
關(guān)于SpringBoot
SpringBoot的入口程序一般如下:
@SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
即,調(diào)用 SpringApplication.run()
方法來(lái)啟動(dòng)程序,第一個(gè)參數(shù)是一個(gè)類(lèi),該類(lèi)需要被 @SpringBootApplication
注解所修飾。
@SpringBootApplication
該注解包含了以下3個(gè)注解:
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan
也就是說(shuō), @SpringBootApplication
包含了上面提到的Java配置的兩個(gè)注解 @Configuration
和 @ComponentScan
。
換句話(huà)說(shuō), @SpringBootApplication
所修飾的類(lèi)就是程序的主配置類(lèi)。
有一點(diǎn)需要注意的是,在默認(rèn)情況下(沒(méi)有指定包掃描路徑),會(huì)自動(dòng)掃描主配置類(lèi)所在的包(及其子包)。因此,該包及子包下的組件類(lèi)和配置類(lèi)都會(huì)被掃描。
當(dāng)然也可以顯式指定包掃描路徑,需要注意的是,其屬性名是 scanBasePakcages
,而不是 basePackages
。
對(duì)比下面兩個(gè)注解:
- @ComponentScan(basePackages = "com.example.demo.pojo")
- @SpringBootApplication(scanBasePackages = "com.example.demo.pojo")
若顯式指定了包掃描路徑,則會(huì)覆蓋默認(rèn)設(shè)置(主配置類(lèi)所在的包及子包不會(huì)被掃描)。
到此這篇關(guān)于Spring component-scan XML配置與@ComponentScan注解配置的文章就介紹到這了,更多相關(guān)Spring XML配置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 基于@ComponentScan注解及其XML配置方式
- 關(guān)于@ComponentScan注解的用法及作用說(shuō)明
- SpringBoot中@ComponentScan注解過(guò)濾排除不加載某個(gè)類(lèi)的3種方法
- @AutoConfigurationPackage與@ComponentScan注解區(qū)別
- spring?boot自動(dòng)裝配之@ComponentScan注解用法詳解
- Spring @ComponentScan注解使用案例詳細(xì)講解
- Spring @ComponentScan注解掃描組件原理
- 基于ComponentScan注解的掃描范圍及源碼解析
相關(guān)文章
Kotlin 和 Java 混合開(kāi)發(fā)入門(mén)教程
這篇文章主要介紹了入門(mén) Kotlin 和 Java 混合開(kāi)發(fā),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09java實(shí)現(xiàn)多線(xiàn)程文件的斷點(diǎn)續(xù)傳
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)多線(xiàn)程文件的斷點(diǎn)續(xù)傳,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06SpringBoot消息國(guó)際化配置實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了SpringBoot消息國(guó)際化配置實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07Java并發(fā)Map面試線(xiàn)程安全數(shù)據(jù)結(jié)構(gòu)全面分析
本文將探討如何在Java中有效地應(yīng)對(duì)這些挑戰(zhàn),介紹一種強(qiáng)大的工具并發(fā)Map,它能夠幫助您管理多線(xiàn)程環(huán)境下的共享數(shù)據(jù),確保數(shù)據(jù)的一致性和高性能,深入了解Java中的并發(fā)Map實(shí)現(xiàn),包括ConcurrentHashMap和ConcurrentSkipListMap,及相關(guān)知識(shí)點(diǎn)2023-09-09Java編寫(xiě)時(shí)間工具類(lèi)ZTDateTimeUtil的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用Java編寫(xiě)時(shí)間工具類(lèi)ZTDateTimeUtil,文中的示例代碼講解詳細(xì),有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11強(qiáng)烈推薦MyBatis?三種批量插入方式的比較
這篇文章主要介紹了強(qiáng)烈推薦MyBatis?三種批量插入方式的比較,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07ScheduledThreadPoolExecutor巨坑解決
這篇文章主要為大家介紹了使用ScheduledThreadPoolExecutor遇到的巨坑解決示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Java實(shí)現(xiàn)數(shù)據(jù)更新和事件通知的觀(guān)察者模式
Java觀(guān)察者模式是一種行為型設(shè)計(jì)模式,用于實(shí)現(xiàn)對(duì)象間的一對(duì)多依賴(lài)關(guān)系。當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),它的所有依賴(lài)對(duì)象都會(huì)收到通知并自動(dòng)更新。觀(guān)察者模式可以實(shí)現(xiàn)松耦合,增強(qiáng)了系統(tǒng)的可維護(hù)性和可拓展性2023-04-04