2021-07-01閱讀小筆記:Spring ioc 之組件掃描

1、包掃描指定掃描路徑的方式有幾種?分別如何指定?

我們可以利用@ConponentScan註解對指定路徑下的組件進行掃描,然後注入到Spring容器中。

指定掃描路徑有兩種方式:指定包路徑和指定類

1.1 指定包路徑

例子:

@ComponentScan(basePackages = "com.github.howinfun.demo.ioc.componentscan")
public class Configuration {
}

容器會掃描指定的包路徑下所有帶註解「@Component及擴展註解」的類;指定包路徑不但可以使用 basePackages 屬性,還可以利用 value 屬性,他們是同等的。

1.2 指定類

例子:

@ComponentScan(basePackageClasses = Configuration.class)
public class Configuration {
}

容器會掃描指定類所在路徑及子路徑下的所有帶註解「@Component及擴展註解」的類。

1.3 如何使用多個 @ComponentScan 註解

我們可以利用Spring提供的 @ComponentScans 註解來配置多個 @ComponentScan

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
public @interface ComponentScans {
    ComponentScan[] value();
}

這個註解是在 Spring 4.3 中提供的,比較舊的版本看不到,也用不着。

2、包掃描如何處理過濾規則?默認有哪幾種規則?

@ComponentScan 註解通過 includeFiltersexcludeFilters 屬性來處理過濾規則,默認的是使用過濾規則是掃描帶 @Repository、@Service、@Controller、@Component註解的組件,這個可看接口註釋:

/**
 * Indicates whether automatic detection of classes annotated with {@code @Component}
 * {@code @Repository}, {@code @Service}, or {@code @Controller} should be enabled.
 */
boolean useDefaultFilters() default true;

2.1 過濾規則支持:

Spring 支持的所有過濾器類型:註解、指定類型、切面、正則、自定義.

public enum FilterType {

	/**
	 * Filter candidates marked with a given annotation.
	 * @see org.springframework.core.type.filter.AnnotationTypeFilter
	 */
	ANNOTATION,

	/**
	 * Filter candidates assignable to a given type.
	 * @see org.springframework.core.type.filter.AssignableTypeFilter
	 */
	ASSIGNABLE_TYPE,

	/**
	 * Filter candidates matching a given AspectJ type pattern expression.
	 * @see org.springframework.core.type.filter.AspectJTypeFilter
	 */
	ASPECTJ,

	/**
	 * Filter candidates matching a given regex pattern.
	 * @see org.springframework.core.type.filter.RegexPatternTypeFilter
	 */
	REGEX,

	/** Filter candidates using a given custom
	 * {@link org.springframework.core.type.filter.TypeFilter} implementation.
	 */
	CUSTOM

}

2.2 例子:

1、根據註解和指定類過濾

@ComponentScan(basePackageClasses = {Configuration.class}
                                    // 指定類型爲Color的組件不注入,包括子類
                ,excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = Color.class)
                                    // 指定帶@Component註解的組件不注入
                                    ,@ComponentScan.Filter(type = FilterType.ANNOTATION,value = Component.class)})
public class Configuration {
}

2、自定義過濾器:

@ComponentScan(basePackageClasses = {Configuration.class}
                                    // 指定類型爲Color的組件不注入,包括子類
                ,excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = Color.class),
                                    // 指定帶@Component註解的組件不注入
                                @ComponentScan.Filter(type = FilterType.ANNOTATION,value = Component.class),
                                // 如果父類是Color,則不注入
                                @ComponentScan.Filter(type = FilterType.CUSTOM,value = CustomFilter.class)})
public class Configuration {
}
/**
 * 自定義組件掃描過濾器
 * 如果父類是Color,則返回true
 * @author winfun
 * @date 2021/7/1 3:09 下午
 **/
public class CustomFilter implements TypeFilter {

    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        /**
         * metadataReader :the metadata reader for the target class
         *      通過這個 Reader ,可以讀取到正在掃描的類的信息(包括類的信息、類上標註的註解等)
         * metadataReaderFactory :a factory for obtaining metadata readers for other classes (such as superclasses and interfaces)
         *      藉助這個 Factory ,可以獲取到其他類的 Reader ,進而獲取到那些類的信息
         *      可以這樣理解:藉助 ReaderFactory 可以獲取到 Reader ,藉助 Reader 可以獲取到指定類的信息
         */
        // 獲取類元數據
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 獲取類註解元數據
        AnnotationMetadata aNnotationMetadata = metadataReader.getAnnotationMetadata();
        if (classMetadata.getSuperClassName().equals(Color.class)){
            return true;
        }
        return false;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章