在一個項目開發中,通常會把項目分爲
一、DAO層(數據訪問層):專門負責數據庫交互 CRUD(增查改刪),好比在mysql數據庫裏生成一條訂單數據。java
二、Service層(業務邏輯層) : 負責業務邏輯的處理,好比購買東西的業務,須要調用DAO層的方法扣減商品記錄裏的庫存數量,而後生成一條訂單記錄。mysql
三、Controller層(控制層) : 接收頁面的請求,調用業務邏輯層去處理,將業務邏輯層處理返回的結果返回給頁面。spring
spring中對每一層都提供了相應的註解進行標識:sql
spring還提供了 @Component 組件,沒有明確的角色,只是標明該類要註冊到spring容器中。數據庫
spring可使用 @ComponentScan 註解掃描指定包下標有上面那些註解的類註冊到spring容器中。數組
一、基礎使用app
下面配置類使用了包掃描註解@ComponentScan,並指定了掃描的包名爲com.suzhe.spring.basic.scan, spring啓動的時候就會掃描該包下全部的符合條件的類,並注入到spring容器中。ide
@Configuration //告訴Spring這是一個配置類 //包掃描:若是沒有配置則默認掃描爲當前類所在包及其子包 @ComponentScan(value = "com.suzhe.spring.basic.scan") public class ScanConfig { }
添加幾個類:其中Message1 沒有註解,不符合條件測試
@Controller public class GreetingController { }
@Service public class GreetingService { }
@Repository public class GreetingDao { public String getMessage(){ return "welcome"; } }
@Component public class Message { }
public class Message1 { }
運行測試.net
@Test public void test1(){ AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(ScanConfig.class); //獲取容器中全部註冊的bean的name,返回一個數組 String[] names = app.getBeanDefinitionNames(); for(String name:names){ System.out.println(name); } }
能夠看出spring把指定包下符合條件的類都註冊到了容器中
值得注意的是,這些註解都有一個 value屬性,是指定註冊到spring中實例的name,默認爲 類名首字母小寫。
咱們能夠設置以下
@Service(value = "gs") public class GreetingService { }
再次運行測試,能夠看到註冊到spring中bean實例的name變成了gs。
同理,其餘註解也同樣。
二、擴展-包含過濾
註解@ComponentScan 還提供includeFilters屬性指定掃描的時候只須要包含哪些組件。
其中Filter有下面幾種過濾類型:
FilterType.ANNOTATION:按照註解
FilterType.ASSIGNABLE_TYPE:按照給定的類型;
FilterType.ASPECTJ:使用ASPECTJ表達式
FilterType.REGEX:使用正則指定
FilterType.CUSTOM:使用自定義規則
示例配置類1
該類配置了FilterType.ANNOTATION和FilterType.ASSIGNABLE_TYPE ,那麼就只有註解爲@Service的類和Message會被註冊到spring容器中。
須要注意的是useDefaultFilters設置爲false。
@Configuration //告訴Spring這是一個配置類 //包掃描:若是沒有配置則默認掃描爲當前類所在包及其子包 @ComponentScan(value = "com.suzhe.spring.basic.scan",includeFilters ={ @ComponentScan.Filter(type= FilterType.ANNOTATION, classes={Service.class}), @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes={Message.class}), }, useDefaultFilters=false) public class ScanIncludeConfig { }
測試運行
@Test public void test2(){ AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(ScanIncludeConfig.class); String[] names = app.getBeanDefinitionNames(); for(String name:names){ System.out.println(name); } }
從下面的結果能夠看出,只有兩個符合過濾條件的類注入到了spring容器中。
同時咱們還能夠自定義過濾器,以下
public class CustomTypeFilter implements TypeFilter{ private ClassMetadata classMetadata; /* * MetadataReader:讀取到當前正在掃描類的信息 * MetadataReaderFactory:能夠獲取到其餘任何類信息 */ @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //獲取當前類註解的信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //獲取當前正在掃描的類信息 classMetadata = metadataReader.getClassMetadata(); //獲取當前類資源(類的路徑) Resource resource = metadataReader.getResource(); String className = classMetadata.getClassName(); System.out.println("----->"+className); if(className.contains("Controller")){//當類名包含Controller字符, 則匹配成功,返回true return true; } return false; } }
經過FilterType.CUSTOM 指定過濾器CustomTypeFilter ,那麼spring就只會註冊符合CustomTypeFilter過濾條件的類。
@Configuration //告訴Spring這是一個配置類 //包掃描:若是沒有配置則默認掃描爲當前類所在包及其子包 @ComponentScan(value = "com.suzhe.spring.basic.scan",includeFilters ={ @ComponentScan.Filter(type=FilterType.CUSTOM,classes={CustomTypeFilter.class}), }, useDefaultFilters=false) public class ScanIncludeCustomConfig { }
測試運行
@Test public void test02(){ AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(ScanIncludeCustomConfig.class); String[] names = app.getBeanDefinitionNames(); for(String name:names){ System.out.println(name); } }
能夠看到只有符合條件的GreetingController 被註冊了。
同時@ComponentScan還提供了排除的過濾功能:
useDefaultFilters=true excludeFilters = Filter[] :指定掃描的時候按照什麼規則排除哪些組件
includeFilters是包含哪些,excludeFilters是排除哪些,其餘的都同樣,這裏再也不作過多的說明。