Spring scan

解析

  • Spring 注解形式使用有下面两种方式
    1. 通过AnnotationConfigApplicationContext参数:扫描包
    2. 通过 xml 配置context:component-scan属性base-package
  1. AnnotationConfigApplicationContext aac =
  2. new AnnotationConfigApplicationContext("com.huifer.source.spring.ann");
  1. <context:component-scan base-package="com.huifer.source.spring.ann">
  2. </context:component-scan>
  • 目标明确开始找入口方法
  • AnnotationConfigApplicationContext直接点进去看就找到了
  1. public AnnotationConfigApplicationContext(String... basePackages) {
  2. this();
  3. // 扫描包
  4. scan(basePackages);
  5. refresh();
  6. }
  • context:component-scan寻找方式:冒号:钱+NamespaceHandler 或者全文搜索component-scan,最终找到org.springframework.context.config.ContextNamespaceHandler
  1. public class ContextNamespaceHandler extends NamespaceHandlerSupport {
  2. @Override
  3. public void init() {
  4. registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
  5. registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
  6. registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
  7. registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
  8. registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
  9. registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
  10. registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
  11. registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
  12. }
  13. }

org.springframework.context.annotation.ComponentScanBeanDefinitionParser

image-20200115093602651

  • 实现BeanDefinitionParser直接看parse方法
  1. @Override
  2. @Nullable
  3. public BeanDefinition parse(Element element, ParserContext parserContext) {
  4. // 获取 base-package 属性值
  5. String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
  6. // 处理 ${}
  7. basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
  8. // 分隔符`,;\t\n`切分
  9. String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
  10. ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
  11. // Actually scan for bean definitions and register them.
  12. // 扫描对象创建
  13. ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
  14. // 执行扫描方法
  15. Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
  16. // 注册组件,触发监听
  17. registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
  18. return null;
  19. }
  • 回过头看AnnotationConfigApplicationContext

org.springframework.context.annotation.AnnotationConfigApplicationContext

  1. public AnnotationConfigApplicationContext(String... basePackages) {
  2. this();
  3. // 扫描包
  4. scan(basePackages);
  5. refresh();
  6. }
  1. private final ClassPathBeanDefinitionScanner scanner;
  2. @Override
  3. public void scan(String... basePackages) {
  4. Assert.notEmpty(basePackages, "At least one base package must be specified");
  5. this.scanner.scan(basePackages);
  6. }
  • org.springframework.context.annotation.ClassPathBeanDefinitionScanner.scan
  1. public int scan(String... basePackages) {
  2. // 获取bean数量
  3. int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
  4. // 执行扫描
  5. doScan(basePackages);
  6. // Register annotation config processors, if necessary.
  7. if (this.includeAnnotationConfig) {
  8. AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
  9. }
  10. return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
  11. }
  • 这个地方doScan似曾相识,他就是org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse中的doScan,下一步解析 doScan

org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan

  1. protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
  2. Assert.notEmpty(basePackages, "At least one base package must be specified");
  3. Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
  4. for (String basePackage : basePackages) {
  5. // 寻找组件
  6. Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
  7. for (BeanDefinition candidate : candidates) {
  8. // bean 作用域设置
  9. ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
  10. // 设置生命周期
  11. candidate.setScope(scopeMetadata.getScopeName());
  12. // 创建beanName
  13. String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
  14. if (candidate instanceof AbstractBeanDefinition) {
  15. // 设置默认属性 具体方法:org.springframework.beans.factory.support.AbstractBeanDefinition.applyDefaults
  16. postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
  17. }
  18. if (candidate instanceof AnnotatedBeanDefinition) {
  19. // 读取Lazy,Primary 等注解
  20. AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
  21. }
  22. // bean的重复检查
  23. if (checkCandidate(beanName, candidate)) {
  24. // 创建 BeanDefinitionHolder
  25. BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
  26. // 代理对象的处理
  27. definitionHolder =
  28. AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
  29. // 放入list中,最后返回用
  30. beanDefinitions.add(definitionHolder);
  31. // 注册bean
  32. registerBeanDefinition(definitionHolder, this.registry);
  33. }
  34. }
  35. }
  36. return beanDefinitions;
  37. }

org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents

  1. public Set<BeanDefinition> findCandidateComponents(String basePackage) {
  2. // 扫描
  3. if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
  4. return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
  5. }
  6. else {
  7. return scanCandidateComponents(basePackage);
  8. }
  9. }
  1. /**
  2. * 扫描当前包路径下的资源
  3. * @param basePackage
  4. * @return
  5. */
  6. private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
  7. Set<BeanDefinition> candidates = new LinkedHashSet<>();
  8. try {
  9. // 字符串拼接出一个编译后的路径 classpath://
  10. // 这里替换了通配符
  11. String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
  12. resolveBasePackage(basePackage) + '/' + this.resourcePattern;
  13. // 获取资源
  14. Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
  15. // 日志级别
  16. boolean traceEnabled = logger.isTraceEnabled();
  17. boolean debugEnabled = logger.isDebugEnabled();
  18. for (Resource resource : resources) {
  19. if (traceEnabled) {
  20. logger.trace("Scanning " + resource);
  21. }
  22. if (resource.isReadable()) {
  23. try {
  24. // 获取 MetadataReader
  25. MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
  26. // 判断是否是 Component
  27. if (isCandidateComponent(metadataReader)) {
  28. ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
  29. sbd.setResource(resource);
  30. sbd.setSource(resource);
  31. if (isCandidateComponent(sbd)) {
  32. if (debugEnabled) {
  33. logger.debug("Identified candidate component class: " + resource);
  34. }
  35. candidates.add(sbd);
  36. }
  37. else {
  38. if (debugEnabled) {
  39. logger.debug("Ignored because not a concrete top-level class: " + resource);
  40. }
  41. }
  42. }
  43. else {
  44. if (traceEnabled) {
  45. logger.trace("Ignored because not matching any filter: " + resource);
  46. }
  47. }
  48. }
  49. catch (Throwable ex) {
  50. throw new BeanDefinitionStoreException(
  51. "Failed to read candidate component class: " + resource, ex);
  52. }
  53. }
  54. else {
  55. if (traceEnabled) {
  56. logger.trace("Ignored because not readable: " + resource);
  57. }
  58. }
  59. }
  60. }
  61. catch (IOException ex) {
  62. throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
  63. }
  64. return candidates;
  65. }

org.springframework.context.annotation.ScopeMetadataResolver#resolveScopeMetadata

  1. /**
  2. * 生命周期设置
  3. *
  4. * @param definition the target bean definition
  5. * @return
  6. */
  7. @Override
  8. public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
  9. ScopeMetadata metadata = new ScopeMetadata();
  10. // 判断是否属于 AnnotatedBeanDefinition
  11. if (definition instanceof AnnotatedBeanDefinition) {
  12. AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
  13. AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
  14. annDef.getMetadata(), this.scopeAnnotationType);
  15. if (attributes != null) {
  16. // 获取 value 属性值并且设置
  17. metadata.setScopeName(attributes.getString("value"));
  18. // 获取 proxyMode 属性值并且设置
  19. ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
  20. if (proxyMode == ScopedProxyMode.DEFAULT) {
  21. proxyMode = this.defaultProxyMode;
  22. }
  23. metadata.setScopedProxyMode(proxyMode);
  24. }
  25. }
  26. return metadata;
  27. }
  • org.springframework.context.annotation.AnnotationScopeMetadataResolverTests#resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation测试用例
  1. @Test
  2. public void resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation() {
  3. AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithScopedProxy.class);
  4. ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd);
  5. assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata);
  6. assertEquals("request", scopeMetadata.getScopeName());
  7. assertEquals(TARGET_CLASS, scopeMetadata.getScopedProxyMode());
  8. }

image-20200115141708702

org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName

  • 创建 beanName org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName
  1. @Override
  2. public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
  3. if (definition instanceof AnnotatedBeanDefinition) {
  4. // 如果存在bean(value="") value存在
  5. String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
  6. if (StringUtils.hasText(beanName)) {
  7. // Explicit bean name found.
  8. return beanName;
  9. }
  10. }
  11. // Fallback: generate a unique default bean name.
  12. // 创建beanName
  13. return buildDefaultBeanName(definition, registry);
  14. }
  1. @Nullable
  2. protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
  3. AnnotationMetadata amd = annotatedDef.getMetadata();
  4. Set<String> types = amd.getAnnotationTypes();
  5. String beanName = null;
  6. for (String type : types) {
  7. AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
  8. if (attributes != null && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
  9. // 获取注解的value 属性值
  10. Object value = attributes.get("value");
  11. if (value instanceof String) {
  12. String strVal = (String) value;
  13. // 判断是否存在值
  14. if (StringUtils.hasLength(strVal)) {
  15. if (beanName != null && !strVal.equals(beanName)) {
  16. throw new IllegalStateException("Stereotype annotations suggest inconsistent " +
  17. "component names: '" + beanName + "' versus '" + strVal + "'");
  18. }
  19. // beanName = value属性值
  20. beanName = strVal;
  21. }
  22. }
  23. }
  24. }
  25. return beanName;
  26. }
  1. @Service(value = "dhc")
  2. public class DemoService {
  3. }

image-20200115143315633

  • org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.support.BeanDefinitionRegistry)
    • org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition)
  1. protected String buildDefaultBeanName(BeanDefinition definition) {
  2. // 获取bean class name
  3. String beanClassName = definition.getBeanClassName();
  4. Assert.state(beanClassName != null, "No bean class name set");
  5. // 获取短类名,
  6. String shortClassName = ClassUtils.getShortName(beanClassName);
  7. // 第一个字母小写
  8. return Introspector.decapitalize(shortClassName);
  9. }
  1. @Configuration
  2. public class BeanConfig {
  3. @Scope(value =ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  4. @Bean(value = "hc")
  5. public Ubean f() {
  6. return new Ubean();
  7. }
  8. }

image-20200115143456554

org.springframework.context.annotation.ClassPathBeanDefinitionScanner#postProcessBeanDefinition

  • 这个方法没什么难点,直接是 set 方法
  1. protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
  2. beanDefinition.applyDefaults(this.beanDefinitionDefaults);
  3. if (this.autowireCandidatePatterns != null) {
  4. beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
  5. }
  6. }
  1. public void applyDefaults(BeanDefinitionDefaults defaults) {
  2. setLazyInit(defaults.isLazyInit());
  3. setAutowireMode(defaults.getAutowireMode());
  4. setDependencyCheck(defaults.getDependencyCheck());
  5. setInitMethodName(defaults.getInitMethodName());
  6. setEnforceInitMethod(false);
  7. setDestroyMethodName(defaults.getDestroyMethodName());
  8. setEnforceDestroyMethod(false);
  9. }

org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition)

  1. public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
  2. processCommonDefinitionAnnotations(abd, abd.getMetadata());
  3. }
  1. static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
  2. // 获取 lazy 注解
  3. AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
  4. if (lazy != null) {
  5. abd.setLazyInit(lazy.getBoolean("value"));
  6. } else if (abd.getMetadata() != metadata) {
  7. lazy = attributesFor(abd.getMetadata(), Lazy.class);
  8. if (lazy != null) {
  9. abd.setLazyInit(lazy.getBoolean("value"));
  10. }
  11. }
  12. if (metadata.isAnnotated(Primary.class.getName())) {
  13. abd.setPrimary(true);
  14. }
  15. AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
  16. if (dependsOn != null) {
  17. abd.setDependsOn(dependsOn.getStringArray("value"));
  18. }
  19. AnnotationAttributes role = attributesFor(metadata, Role.class);
  20. if (role != null) {
  21. abd.setRole(role.getNumber("value").intValue());
  22. }
  23. AnnotationAttributes description = attributesFor(metadata, Description.class);
  24. if (description != null) {
  25. abd.setDescription(description.getString("value"));
  26. }
  27. }
  • 方法思路:
    1. 获取注解的属性值
    2. 设置注解属性

org.springframework.context.annotation.ClassPathBeanDefinitionScanner#checkCandidate

  • 重复检查
  1. protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
  2. // 判断当前 beanName 是否在注册表中
  3. if (!this.registry.containsBeanDefinition(beanName)) {
  4. return true;
  5. }
  6. // 从注册表中获取
  7. BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);
  8. // 当前的bean
  9. BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();
  10. if (originatingDef != null) {
  11. existingDef = originatingDef;
  12. }
  13. if (isCompatible(beanDefinition, existingDef)) {
  14. return false;
  15. }
  16. throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName +
  17. "' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " +
  18. "non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]");
  19. }

org.springframework.context.annotation.AnnotationConfigUtils#applyScopedProxyMode

  1. static BeanDefinitionHolder applyScopedProxyMode(
  2. ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
  3. ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
  4. if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
  5. return definition;
  6. }
  7. boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
  8. // 创建代理对象
  9. return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
  10. }