網頁

2020/9/19

Spring Boot @ComponentScan掃描指定套件(包) scan specific package

在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


沒有留言:

張貼留言