在SpringBoot專案通常都直接把類別放在@SpringBootApplication
類所在package下的package,然後Spring預設會掃描這些package並把掛有@Compoment
、@Repository
、@Service
、@Controller
、@Configuration
的類別註冊為Spring bean。
不過如果專案package及類別非常多會造成啟動時很慢,因為要花很多時間去掃描這些package。要改善此情況可設定只掃描特定的package來提高掃描註冊bean的效率。
@ComponentScan
不做任何設定預設會掃描所在package及下面所有package的類。
例如專案中有以下package:
com.abc.demo
com.abc.demo.controller
com.abc.demo.service
com.abc.demo.entity
com.abc.demo.entity.repository
com.abc.demo.util
com.abc.demo.dto
如果@ComponentScan
是設在com.abc.demo
中的配置類,例如AppConfig
如下,則com.abc.demo.*
的package都會被掃描。
AppConfig
package com.abc.demo; // <-- 此package下的package都會被@ComponentScan掃描
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan
@Configuration
public class AppConfig {
}
而@SpringBootApplication
本身即包含了@ComponentScan
,節錄原始碼如下
@SpringBootApplication
...
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}
所以預設Spring Boot專案會掃描@SpringBootApplication
類所在package下的package。例如下面的DemoApplication
掛有@SpringBootApplication
,所以預設會掃描com.abc.demo.*
的package。
DemoApplication
package com.abc.demo; // <-- 此package下的package都會被@ComponentScan掃描
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
為了要避免全掃描的情況,可在@SpringBootApplication
另外設定@ComponentScan
來修改預設的掃描行為。例如設定basePackages
來指定要掃描的package。
下面設定只掃描
com.abc.demo.controller
、
com.abc.demo.service
、
com.abc.demo.repository
中的類,如此一些非bean的package,例如通常很大包的
POJO類packagecom.abc.demo.dto
、
工具類packagecom.abc.demo.util
、
實體類package com.abc.demo.entity
就不需要花時間掃描了。
DemoApplication
package com.abc.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = {
"com.abc.demo.controller",
"com.abc.demo.service",
"com.abc.demo.entity.repository"
})
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
或直接用@SpringBootApplication
相同功能的屬性scanBasePackages
來設定。
DemoApplication
package com.abc.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = {
"com.abc.demo.controller",
"com.abc.demo.service",
"com.abc.demo.entity.repository"
})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
參考github。
沒有留言:
張貼留言