好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Spring ComponentScan的扫描过程解析

XML中的扫描过程

?

1

2

3

4

5

6

7

8

9

<? xml version = "1.0" encoding = "utf-8" ?>

< beans xmlns = "http://HdhCmsTestspringframework.org/schema/beans"

        xmlns:xsi = "http://HdhCmsTestw3.org/2001/XMLSchema-instance"

        xmlns:context = "http://HdhCmsTestspringframework.org/schema/context"

        xsi:schemaLocation="http://HdhCmsTestspringframework.org/schema/beans

     http://HdhCmsTestspringframework.org/schema/beans/spring-beans.xsd http://HdhCmsTestspringframework.org/schema/context https://HdhCmsTestspringframework.org/schema/context/spring-context.xsd"

        default-lazy-init = "false" >

     < context:component-scan base-package = "com.morris.spring.demo.service" />

</ beans >

xml中使用自定义标签context实现,最终会调用到ComponentScanBeanDefinitionParser.parse()方法进行解析。

ComponentScanBeanDefinitionParser.parse()

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

// org.springframework.context.annotation.ComponentScanBeanDefinitionParser#parse

public BeanDefinition parse(Element element, ParserContext parserContext) {

     // 获得base-package指定的包名

     String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);

     basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);

     // base-package中可能有多个,用逗号分隔,转换为数组

     String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,

             ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

 

     // Actually scan for bean definitions and register them.

     // 创建扫描器

     ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);

     // 开始扫描

     Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);

 

     // 注册了一些组件

     // ConfigurationClassPostProcessor

     // AutowiredAnnotationBeanPostProcessor

     // CommonAnnotationBeanPostProcessor

     // EventListenerMethodProcessor

     // DefaultEventListenerFactory

     registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

 

     return null ;

}

ComponentScanBeanDefinitionParser#configureScanner

创建扫描器ClassPathBeanDefinitionScanner

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {

     boolean useDefaultFilters = true ;

     if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {

         useDefaultFilters = Boolean.parseBoolean(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));

     }

 

     // Delegate bean definition registration to scanner class.

     // ClassPathBeanDefinitionScanner构造方法中添加了默认的includeFilters为@Component

     ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);

     scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());

     scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());

 

     if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {

         scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));

     }

 

     try {

         parseBeanNameGenerator(element, scanner);

     }

     catch (Exception ex) {

         parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());

     }

 

     try {

         parseScope(element, scanner);

     }

     catch (Exception ex) {

         parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());

     }

 

     parseTypeFilters(element, scanner, parserContext);

 

     return scanner;

}

怎么知道扫描哪些注解呢?

ClassPathBeanDefinitionScanner构造方法中会注入默认的Filter。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

protected void registerDefaultFilters() {

     // 只扫描@Component注解了的类,而@Sevice、@Configuration、@Controller等注解都被@Component修饰

     this .includeFilters.add( new AnnotationTypeFilter(Component. class ));

     ClassLoader cl = ClassPathScanningCandidateComponentProvider. class .getClassLoader();

     try {

         this .includeFilters.add( new AnnotationTypeFilter(

                 ((Class<? extends Annotation>) ClassUtils.forName( "javax.annotation.ManagedBean" , cl)), false ));

         logger.trace( "JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning" );

     }

     catch (ClassNotFoundException ex) {

         // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.

     }

     try {

         this .includeFilters.add( new AnnotationTypeFilter(

                 ((Class<? extends Annotation>) ClassUtils.forName( "javax.inject.Named" , cl)), false ));

         logger.trace( "JSR-330 'javax.inject.Named' annotation found and supported for component scanning" );

     }

     catch (ClassNotFoundException ex) {

         // JSR-330 API not available - simply skip.

     }

}

在源码中只会扫描@Component注解,而@Sevice、@Configuration、@Controller等注解都被@Component修饰,最终都会被扫描到。

ClassPathBeanDefinitionScanner#doScan

开始扫描:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

// org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {

     Assert.notEmpty(basePackages, "At least one base package must be specified" );

     Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();

     for (String basePackage : basePackages) {

         // 查找basePackage下所有被@Component注解修饰了的类

         Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

         for (BeanDefinition candidate : candidates) {

             // 上面findCandidateComponents只是为BD设置了几个属性,BD的其他属性并没有初始化,所以需要遍历一次初始化属性并注册到registry

             ScopeMetadata scopeMetadata = this .scopeMetadataResolver.resolveScopeMetadata(candidate);

             candidate.setScope(scopeMetadata.getScopeName());

             String beanName = this .beanNameGenerator.generateBeanName(candidate, this .registry);

             if (candidate instanceof AbstractBeanDefinition) {

                 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);

             }

             if (candidate instanceof AnnotatedBeanDefinition) {

                 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);

             }

             if (checkCandidate(beanName, candidate)) {

                 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);

                 definitionHolder =

                         AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this .registry);

                 beanDefinitions.add(definitionHolder);

                 // 注册到registry

                 registerBeanDefinition(definitionHolder, this .registry);

             }

         }

     }

     return beanDefinitions;

}

ClassPathScanningCandidateComponentProvider#scanCandidateComponents

查找basePackage下所有被@Component注解修饰了的类:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

// org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {

     Set<BeanDefinition> candidates = new LinkedHashSet<>();

     try {

         // basePackage=com.morris.spring..service

         // packageSearchPath=classpath*:com/morris/spring/service/**/*.class

         String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +

             resolveBasePackage(basePackage) + '/' + this .resourcePattern;

         // 获取basePackage下所有的class文件

         Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);

         boolean traceEnabled = logger.isTraceEnabled();

         boolean debugEnabled = logger.isDebugEnabled();

         for (Resource resource : resources) {

             if (traceEnabled) {

                 logger.trace( "Scanning " + resource);

             }

             if (resource.isReadable()) {

                 try {

                     // 使用ASM将class文件的内容封装为MetadataReader对象

                     // 注意这里用的不是反射,反射会加载类,占用堆空间

                     MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);

                     // 判断类是否包含@Component注解

                     if (isCandidateComponent(metadataReader)) {

                         // 封装为BD

                         ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);

                         sbd.setSource(resource);

                         if (isCandidateComponent(sbd)) {

                             if (debugEnabled) {

                                 logger.debug( "Identified candidate component class: " + resource);

                             }

                             candidates.add(sbd);

                         }

... ...

     return candidates;

}

registerAnnotationConfigProcessors

注册了多种重要的组件:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(

         BeanDefinitionRegistry registry, @Nullable Object source) {

 

     DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);

     if (beanFactory != null ) {

         if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {

             beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);

         }

         if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {

             beanFactory.setAutowireCandidateResolver( new ContextAnnotationAutowireCandidateResolver());

         }

     }

 

     Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>( 8 );

 

     // BeanFactoryPostProcessor

     if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {

         RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor. class );

         def.setSource(source);

         beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));

     }

 

     // BeanPostProcessor

     if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {

         RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor. class );

         def.setSource(source);

         beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));

     }

 

     // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.

     if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {

         RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor. class );

         def.setSource(source);

         beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));

     }

 

     // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.

     if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {

         RootBeanDefinition def = new RootBeanDefinition();

         try {

             def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,

                     AnnotationConfigUtils. class .getClassLoader()));

         }

         catch (ClassNotFoundException ex) {

             throw new IllegalStateException(

                     "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);

         }

         def.setSource(source);

         beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));

     }

 

     // BeanFactoryPostProcessor

     if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {

         RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor. class );

         def.setSource(source);

         beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));

     }

 

     if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {

         RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory. class );

         def.setSource(source);

         beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));

     }

 

     return beanDefs;

}

扫描的最终结果就是将类上面有@Component注解的类构建为一个BeanDefinition中,Spring容器中有两个集合来存放这些BeanDefinition:

beanDefinitionNames:List<String>,存放所有的BeanDefinition对应的name beanDefinitionMap:Map<String, BeanDefinition>,存放所有的BeanDefinition

注解的扫描过程

注解扫描的使用:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

package com.morris.spring.demo.annotation;

 

import com.morris.spring.demo.service.CityService;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import org.springframework.context.annotation.ComponentScan;

 

@ComponentScan ( "com.morris.spring.service" )

public class ComponentScanDemo {

     public static void main(String[] args) {

         AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ComponentScanDemo. class );

         CityService cityService = applicationContext.getBean(CityService. class );

         cityService.city();

     }

}

使用@ComponentScan注解指定包的扫描,扫描过程将由ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry完成。

ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {

     int registryId = System.identityHashCode(registry);

     if ( this .registriesPostProcessed.contains(registryId)) {

         throw new IllegalStateException(

                 "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);

     }

     if ( this .factoriesPostProcessed.contains(registryId)) {

         throw new IllegalStateException(

                 "postProcessBeanFactory already called on this post-processor against " + registry);

     }

     this .registriesPostProcessed.add(registryId);

     // 重点

     processConfigBeanDefinitions(registry);

}

ConfigurationClassPostProcessor#processConfigBeanDefinitions

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {

     List<BeanDefinitionHolder> configCandidates = new ArrayList<>();

     String[] candidateNames = registry.getBeanDefinitionNames();

     // 先收集有@Configuration、@Component、@ComponentScan、@Import、@ImportResource、@Bean的BD

     for (String beanName : candidateNames) {

         BeanDefinition beanDef = registry.getBeanDefinition(beanName);

         if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null ) {

             if (logger.isDebugEnabled()) {

                 logger.debug( "Bean definition has already been processed as a configuration class: " + beanDef);

             }

         }

         else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this .metadataReaderFactory)) {

             // 进来需要@Component、@ComponentScan、@Import、@ImportResource、@Bean

             configCandidates.add( new BeanDefinitionHolder(beanDef, beanName));

         }

     }

     ... ...

     // Parse each @Configuration class

     ConfigurationClassParser parser = new ConfigurationClassParser(

             this .metadataReaderFactory, this .problemReporter, this .environment,

             this .resourceLoader, this 测试数据ponentScanBeanNameGenerator, registry);

     Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);

     Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());

     do {

         // 开始解析

         parser.parse(candidates);

         parser.validate();

ConfigurationClassParser#doProcessConfigurationClass

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

protected final SourceClass doProcessConfigurationClass(

         ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)

         throws IOException {

     ... ...

     // Process any @ComponentScan annotations

     // 处理@ComponentScan注解,扫描包下带有@Component的注解,与xml中自定义标签context:component-scan的扫描流程一致

     Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(

             sourceClass.getMetadata(), ComponentScans. class , ComponentScan. class );

     if (!componentScans.isEmpty() &&

             ! this .conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {

         for (AnnotationAttributes componentScan : componentScans) {

             // The config class is annotated with @ComponentScan -> perform the scan immediately

             Set<BeanDefinitionHolder> scannedBeanDefinitions =

                     this 测试数据ponentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

             // Check the set of scanned definitions for any further config classes and parse recursively if needed

             for (BeanDefinitionHolder holder : scannedBeanDefinitions) {

                 BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();

                 if (bdCand == null ) {

                     bdCand = holder.getBeanDefinition();

                 }

                 // checkConfigurationClassCandidate这个里面会特殊处理@Configutation为full

                 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this .metadataReaderFactory)) {

                     parse(bdCand.getBeanClassName(), holder.getBeanName());

                 }

             }

         }

     }

     ... ...

     return null ;

}

ComponentScanAnnotationParser#parse

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {

     // 解析@ComponentScan注解,构建ClassPathBeanDefinitionScanner

     // 构建方法中会添加默认的includeFilters为@Component

     ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner( this .registry,

             componentScan.getBoolean( "useDefaultFilters" ), this .environment, this .resourceLoader);

     Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass( "nameGenerator" );

     boolean useInheritedGenerator = (BeanNameGenerator. class == generatorClass);

     scanner.setBeanNameGenerator(useInheritedGenerator ? this .beanNameGenerator :

             BeanUtils.instantiateClass(generatorClass));

     ScopedProxyMode scopedProxyMode = componentScan.getEnum( "scopedProxy" );

     if (scopedProxyMode != ScopedProxyMode.DEFAULT) {

         scanner.setScopedProxyMode(scopedProxyMode);

     }

     else {

         Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass( "scopeResolver" );

         scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));

     }

     scanner.setResourcePattern(componentScan.getString( "resourcePattern" ));

     for (AnnotationAttributes filter : componentScan.getAnnotationArray( "includeFilters" )) {

         for (TypeFilter typeFilter : typeFiltersFor(filter)) {

             scanner.addIncludeFilter(typeFilter);

         }

     }

     for (AnnotationAttributes filter : componentScan.getAnnotationArray( "excludeFilters" )) {

         for (TypeFilter typeFilter : typeFiltersFor(filter)) {

             scanner.addExcludeFilter(typeFilter);

         }

     }

     boolean lazyInit = componentScan.getBoolean( "lazyInit" );

     if (lazyInit) {

         scanner.getBeanDefinitionDefaults().setLazyInit( true );

     }

     Set<String> basePackages = new LinkedHashSet<>();

     String[] basePackagesArray = componentScan.getStringArray( "basePackages" );

     for (String pkg : basePackagesArray) {

         String[] tokenized = StringUtils.tokenizeToStringArray( this .environment.resolvePlaceholders(pkg),

                 ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

         Collections.addAll(basePackages, tokenized);

     }

     for (Class<?> clazz : componentScan.getClassArray( "basePackageClasses" )) {

         basePackages.add(ClassUtils.getPackageName(clazz));

     }

     if (basePackages.isEmpty()) {

         basePackages.add(ClassUtils.getPackageName(declaringClass));

     }

     scanner.addExcludeFilter( new AbstractTypeHierarchyTraversingFilter( false , false ) {

         @Override

         protected boolean matchClassName(String className) {

             return declaringClass.equals(className);

         }

     });

     // 开始扫描

     return scanner.doScan(StringUtils.toStringArray(basePackages));

}

可以发现注解的扫描最后会调用ClassPathBeanDefinitionScanner#doScan(),与XML中的扫描是同一个方法。

总结

XML的扫描过程发生在obtainFreshBeanFactory(),也就是创建BeanFactory时,而注解的扫描过程发生在invokeBeanFactoryPostProcessors()。 XML的扫描会在obtainFreshBeanFactory()时注入ConfigurationClassPostProcessor,而注解的扫描是在创建AnnotationConfigApplicationContext实例时注入ConfigurationClassPostProcessor,如果xml扫描到的类带有@ComponentScan注解,那么还会继续在invokeBeanFactoryPostProcessors()阶段继续扫描。

到此这篇关于spring ComponentScan的扫描过程的文章就介绍到这了,更多相关spring ComponentScan扫描内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

原文链接:https://blog.csdn.net/u022812849/article/details/123494558

查看更多关于Spring ComponentScan的扫描过程解析的详细内容...

  阅读:13次