看這篇文章以前能夠先了解以前的跟蹤流程,https://www.jianshu.com/p/4934233f0eadjava
代碼過寬,能夠shift + 鼠標滾輪 左右滑動查看node
這篇文章主要跟蹤spring配置文件中component-scan標籤,查看它是怎樣被解析掃描生成對應的beanDefinition。web
在applicationContext.xml中作如下配置:spring
<!-- 啓動組件掃描,排除@Controller組件,該組件由SpringMVC配置文件掃描 --> <context:component-scan base-package="cn.mrdear"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.RestController" /> </context:component-scan>
以DefaultBeanDefinitionDocumentReader類中的parseBeanDefinitions方法做爲開始,向下跟蹤。express
/** * Parse the elements at the root level in the document: * "import", "alias", "bean". * * 解析在文檔中根層級的元素:"import", "alias", "bean". */ protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { //默認名稱空間是"http://www.springframework.org/schema/beans" //進入條件 if (delegate.isDefaultNamespace(root)) { //獲取根元素下的子Node,注意,Node不必定是子標籤,多是回車,多是註釋 NodeList nl = root.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { //拿到了<beans>下的子標籤 Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { //若是該標籤屬於beans的名稱空間,則進入這個方法 //xmlns="http://www.springframework.org/schema/beans" parseDefaultElement(ele, delegate); } else { //若是該標籤屬於其餘的名稱空間好比:context,aop等 //xmlns:aop="http://www.springframework.org/schema/aop" //xmlns:context="http://www.springframework.org/schema/context" delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
對以上方法不太瞭解的能夠先看下這篇文章:api
https://www.jianshu.com/p/a0cfaedf3fc5數組
由於component-scan標籤屬於context名稱空間,因此走這個方法。app
delegate.parseCustomElement(ele);
這個方法的實如今BeanDefinitionParserDelegate類中ide
public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); } //containingBd入參傳遞爲null public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { //獲取標籤所屬的名稱空間 //http://www.springframework.org/schema/context String namespaceUri = getNamespaceURI(ele); //每一個名稱空間對應一個處理器,拿到對應context的處理器 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } //進入這個方法 return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
雖然context對應的處理器是ContextNamespaceHandler,但其實是調用其父類NamespaceHandlerSupport類中的parse方法。post
/** * Parses the supplied {@link Element} by delegating to the {@link BeanDefinitionParser} that is * registered for that {@link Element}. * * 經過委派給BeanDefinitionParser來解析元素,併爲該元素註冊 */ @Override public BeanDefinition parse(Element element, ParserContext parserContext) { return findParserForElement(element, parserContext).parse(element, parserContext); }
先查看findParserForElement方法,此方法仍是在NamespaceHandlerSupport類中。
/** * Locates the {@link BeanDefinitionParser} from the register implementations using * the local name of the supplied {@link Element}. * * 經過元素的部分名稱,去從註冊器實現中定位BeanDefinitionParser */ private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { //拿到標籤的名稱(不包含名稱空間) //component-scan String localName = parserContext.getDelegate().getLocalName(element); //parsers是一個HashMap, //在生成處理器的時候,會初始化一系列解析器,每個解析器對應着一個標籤名稱 //以名稱作key,解析器做爲value,放入到parsers屬性中 //這裏能夠經過標籤名稱拿到對應的解析器 BeanDefinitionParser parser = this.parsers.get(localName); if (parser == null) { parserContext.getReaderContext().fatal( "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); } return parser; }
找到解析器後,調用解析器的parse方法。
這裏的解析器是ComponentScanBeanDefinitionParser類,進入parse方法查看
/** * 解析指定的Element,而後註冊結果BeanDefinition到內嵌在ParserContext裏的bean factory中。 */ @Override public BeanDefinition parse(Element element, ParserContext parserContext) { //獲取component-scan標籤的base-package屬性值 //cn.mrdear String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); //若是有佔位符,則解析全部的佔位符 basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); //字符串中有" ,;\n\t"等符號就看作分隔符,分割成數組 String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them. // 掃描bean definition 並註冊它們 // 1.配置掃描器 ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); // 2.利用掃描器掃描包,並註冊bean definition Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); // 3. 註冊組件 registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
跟蹤標記1的方法
此方法在ComponentScanBeanDefinitionParser類中實現
// 1.配置掃描器 ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); //進入方法 protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { boolean useDefaultFilters = true; //拿到component-scan標籤的use-default-filters屬性,沒有配置則爲true if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) { useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)); } // Delegate bean definition registration to scanner class. // 1.1將bean definition的工廠委派給scanner類 ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters); //這裏將閱讀器上下文中拿到的根web應用上下文做爲scanner的ResourceLoader, //根web應用上下文默認實現爲XmlWebApplicationContext,實現了ResourceLoader接口, //因此能夠做爲ResourceLoader scanner.setResourceLoader(parserContext.getReaderContext().getResourceLoader()); //初始化scanner時使用默認的StandardEnvironment做爲environment, //這裏拿到了閱讀器上下文中的environment,StandardServletEnvironment //其實閱讀器中的environment拿的是XmlWebApplicationContext的environment scanner.setEnvironment(parserContext.getReaderContext().getEnvironment()); //獲取代理類的defaults屬性中,對標籤屬性的一些默認設置 scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults()); //這裏爲null scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns()); //拿到component-scan標籤的resource-pattern屬性,這裏沒有設置 if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) { scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE)); } try { //1.2解析name-generator屬性 parseBeanNameGenerator(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } try { //1.3解析Scope parseScope(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } //1.4解析類過濾器 parseTypeFilters(element, scanner, parserContext); return scanner; }
跟蹤標記1.1的方法
此方法在ComponentScanBeanDefinitionParser類中實現
// 1.1將bean definition的註冊委派給scanner類 ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters); //入參傳遞了bean工廠,useDefaultFilters爲true protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) { return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters); }
看下ClassPathBeanDefinitionScanner類的構造實現
//由於默認的工廠DefaultListableBeanFactory沒有實現EnvironmentCapable接口 //因此從新建立了一個environment,與上下文的StandardServletEnvironment不一樣, //這個environment是StandardEnvironment類型,在environment初始化的同時,會將 //systemProperties和systemEnvironment讀取到environment內部 public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) { this(registry, useDefaultFilters, getOrCreateEnvironment(registry)); } public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) { //調用了父類的構造 super(useDefaultFilters, environment); Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); //拿到bean工廠的引用 this.registry = registry; // Determine ResourceLoader to use. // 默認bean工廠沒有實現ResourceLoader接口,這裏默認使用PathMatchingResourcePatternResolver // 做爲ResourceLoader if (this.registry instanceof ResourceLoader) { setResourceLoader((ResourceLoader) this.registry); } }
再進入父類構造中查看初始化了哪些屬性
進入ClassPathScanningCandidateComponentProvider類中,查看對應的構造方法
public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters, Environment environment) { //由於useDefaultFilters設置爲了true,因此下面的方法會被調用 if (useDefaultFilters) { registerDefaultFilters(); } Assert.notNull(environment, "Environment must not be null"); //拿到先前新建的StandardEnvironment引用 this.environment = environment; } /** * Register the default filter for {@link Component @Component}. * <p>This will implicitly register all annotations that have the * {@link Component @Component} meta-annotation including the * {@link Repository @Repository}, {@link Service @Service}, and * {@link Controller @Controller} stereotype annotations. * <p>Also supports Java EE 6's {@link javax.annotation.ManagedBean} and * JSR-330's {@link javax.inject.Named} annotations, if available. * * 爲@Component註解註冊默認的過濾器。 * 隱式的註冊全部包含@Component元註解的註解,包括@Repository、@Service、@Controller * 等老舊的註解。 * 也支持Java EE 6的javax.annotation.ManagedBean和JSR-330的javax.inject.Named註解 */ @SuppressWarnings("unchecked") protected void registerDefaultFilters() { //includeFilters是一個LinkedList,存放註解類型過濾器, //只有符合過濾器的註解類型才能生成bean definition //1.1.1瞭解下AnnotationTypeFilter的構造實現,註解類型爲Component this.includeFilters.add(new AnnotationTypeFilter(Component.class)); //拿到該類的類加載器 ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { //1.1.2查看註解類型爲ManagedBean的AnnotationTypeFilter構造實現 this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false)); logger.debug("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 { //Named註解同1.1.2, //可是這裏沒有相關jar包,因此沒有javax.inject.Named這個類,拋出異常,空捕獲跳出 this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false)); logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } }
跟蹤標記1.1.1的方法
//1.1.1瞭解下AnnotationTypeFilter的構造實現 new AnnotationTypeFilter(Component.class) /** * Create a new AnnotationTypeFilter for the given annotation type. * This filter will also match meta-annotations. To disable the * meta-annotation matching, use the constructor that accepts a * '{@code considerMetaAnnotations}' argument. The filter will * not match interfaces. * * 經過給定的註解類型建立一個新的註解類型過濾器 * 這個過濾器還會匹配元註解 * 若是要禁用元註解匹配,可使用接受considerMetaAnnotations參數的構造方法。 * 這個過濾器不會匹配接口 */ public AnnotationTypeFilter(Class<? extends Annotation> annotationType) { this(annotationType, true, false); } /** * 注意上一層調用構造時的入參,默認considerMetaAnnotations爲true,considerInterfaces爲false * 這說明註解中若是它的元註解匹配過濾器,那麼也算是匹配。 * 過濾的時候不考慮是接口的狀況 */ public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations, boolean considerInterfaces) { //isAnnotationPresent方法是用來查看annotationType上是否有Inherited註解 //其boolean值賦值給父類AbstractTypeHierarchyTraversingFilter的屬性considerInherited中 super(annotationType.isAnnotationPresent(Inherited.class), considerInterfaces); this.annotationType = annotationType; this.considerMetaAnnotations = considerMetaAnnotations; }
跟蹤標記1.1.2的方法
//1.1.2查看註解類型爲ManagedBean的AnnotationTypeFilter構造實現 new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false);
首先經過forName方法,拿到字符串javax.annotation.ManagedBean對應的Class,而後調用AnnotationTypeFilter的構造。
/** * 上一層傳參時considerMetaAnnotations爲false,說明不用考慮註解上的元註解,這個註解不匹配過濾器就過濾掉 */ public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations) { this(annotationType, considerMetaAnnotations, false); } //considerInterfaces依然爲false public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations, boolean considerInterfaces) { //ManagedBean的元註解上依然沒有Inherited,因此considerInherited爲false super(annotationType.isAnnotationPresent(Inherited.class), considerInterfaces); this.annotationType = annotationType; this.considerMetaAnnotations = considerMetaAnnotations; }
跟蹤標記1.2的方法
在ComponentScanBeanDefinitionParser類中實現
//1.2解析name-generator屬性 parseBeanNameGenerator(element, scanner); protected void parseBeanNameGenerator(Element element, ClassPathBeanDefinitionScanner scanner) { //component-scan標籤的name-generator屬性,這裏沒有設置,跳過 if (element.hasAttribute(NAME_GENERATOR_ATTRIBUTE)) { BeanNameGenerator beanNameGenerator = (BeanNameGenerator) instantiateUserDefinedStrategy( element.getAttribute(NAME_GENERATOR_ATTRIBUTE), BeanNameGenerator.class, scanner.getResourceLoader().getClassLoader()); scanner.setBeanNameGenerator(beanNameGenerator); } }
跟蹤標記1.3的方法
在ComponentScanBeanDefinitionParser類中實現
//1.3 解析Scope parseScope(element, scanner); protected void parseScope(Element element, ClassPathBeanDefinitionScanner scanner) { // Register ScopeMetadataResolver if class name provided. // 若是類名被提供,則註冊ScopeMetadataResolver // 標籤上有無scope-resolver屬性 if (element.hasAttribute(SCOPE_RESOLVER_ATTRIBUTE)) { // 若是還同時添加了scoped-proxy屬性則報錯 if (element.hasAttribute(SCOPED_PROXY_ATTRIBUTE)) { throw new IllegalArgumentException( "Cannot define both 'scope-resolver' and 'scoped-proxy' on <component-scan> tag"); } ScopeMetadataResolver scopeMetadataResolver = (ScopeMetadataResolver) instantiateUserDefinedStrategy( element.getAttribute(SCOPE_RESOLVER_ATTRIBUTE), ScopeMetadataResolver.class, scanner.getResourceLoader().getClassLoader()); scanner.setScopeMetadataResolver(scopeMetadataResolver); } // 標籤上有無scoped-proxy屬性 if (element.hasAttribute(SCOPED_PROXY_ATTRIBUTE)) { String mode = element.getAttribute(SCOPED_PROXY_ATTRIBUTE); if ("targetClass".equals(mode)) { scanner.setScopedProxyMode(ScopedProxyMode.TARGET_CLASS); } else if ("interfaces".equals(mode)) { scanner.setScopedProxyMode(ScopedProxyMode.INTERFACES); } else if ("no".equals(mode)) { scanner.setScopedProxyMode(ScopedProxyMode.NO); } else { throw new IllegalArgumentException("scoped-proxy only supports 'no', 'interfaces' and 'targetClass'"); } } }
跟蹤標記1.4的方法
在ComponentScanBeanDefinitionParser類中實現
//1.4解析類過濾器 parseTypeFilters(element, scanner, parserContext); protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) { // Parse exclude and include filter elements. // 解析包含和不包含過濾器元素 //拿到根應用上下文的類加載器 ClassLoader classLoader = scanner.getResourceLoader().getClassLoader(); //拿到全部的子節點 NodeList nodeList = element.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); //拿到的子節點是否是子標籤 if (node.getNodeType() == Node.ELEMENT_NODE) { //獲取子標籤的部分名稱(不包含名稱空間) String localName = parserContext.getDelegate().getLocalName(node); try { //是include-filter標籤的狀況,上下兩個調用的同一個方法,跟蹤其中一個 if (INCLUDE_FILTER_ELEMENT.equals(localName)) { TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext); scanner.addIncludeFilter(typeFilter); } //是exclude-filter標籤的狀況 else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) { TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext); scanner.addExcludeFilter(typeFilter); } } catch (Exception ex) { parserContext.getReaderContext().error( ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } } } }
跟蹤createTypeFilter方法
protected TypeFilter createTypeFilter(Element element, ClassLoader classLoader, ParserContext parserContext) { //獲取標籤上的type屬性和expression屬性對應的值 String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE); String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE); //expression可能帶有佔位符,若是有則解析佔位符 expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression); try { //xml文件中type填寫的是annotation,因此走這個方法 if ("annotation".equals(filterType)) { //將xml中的"org.springframework.stereotype.Controller"字符串解析爲Class //構造已經看過,默認considerMetaAnnotations爲true,considerInterfaces爲false return new AnnotationTypeFilter((Class<Annotation>) classLoader.loadClass(expression)); } else if ("assignable".equals(filterType)) { return new AssignableTypeFilter(classLoader.loadClass(expression)); } else if ("aspectj".equals(filterType)) { return new AspectJTypeFilter(expression, classLoader); } else if ("regex".equals(filterType)) { return new RegexPatternTypeFilter(Pattern.compile(expression)); } else if ("custom".equals(filterType)) { Class<?> filterClass = classLoader.loadClass(expression); if (!TypeFilter.class.isAssignableFrom(filterClass)) { throw new IllegalArgumentException( "Class is not assignable to [" + TypeFilter.class.getName() + "]: " + expression); } return (TypeFilter) BeanUtils.instantiateClass(filterClass); } else { throw new IllegalArgumentException("Unsupported filter type: " + filterType); } } catch (ClassNotFoundException ex) { throw new FatalBeanException("Type filter class not found: " + expression, ex); } }
最後scanner的includeFilters屬性中,默認添加了org.springframework.stereotype.Component的註解過濾器和javax.annotation.ManagedBean的註解過濾器。
scanner的excludeFilters屬性中,自定義添加了xml配置文件中的org.springframework.stereotype.Controller註解過濾器和org.springframework.web.bind.annotation.RestController註解過濾器。
跟蹤標記2的方法
此方法在ClassPathBeanDefinitionScanner類中實現
// 2.利用掃描器掃描包,並註冊bean definition Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); /** * Perform a scan within the specified base packages, * returning the registered bean definitions. * <p>This method does <i>not</i> register an annotation config processor * but rather leaves this up to the caller. * * 掃描指定包,返回被註冊的bean definitions * 這個方法不會註冊annotation config processor,交由調用者處理 */ protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>(); //根據配置,這裏就只有一個"cn.mrdear" for (String basePackage : basePackages) { //2.1掃描候選者的class path Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { //2.2解析@scope註解 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); //2.3AnnotatedBeanDefinition的默認名稱生成規則 String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { //2.4給beanDefinition設置默認值、自動注入的候選者 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { //2.5拿到類上其餘的context名稱空間的註解,若是有的話,獲取其value屬性 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } //2.6檢查beanName是否正確匹配對應的bean Definition,該名稱是否已經被註冊 if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); //應用Scope代理模式 definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); //註冊bean definition registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
跟蹤標記2.1的方法
在ClassPathScanningCandidateComponentProvider類中實現
ClassPathScanningCandidateComponentProvider是ClassPathBeanDefinitionScanner的父類
//2.1掃描候選者的class path Set<BeanDefinition> candidates = findCandidateComponents(basePackage); public Set<BeanDefinition> findCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>(); try { //給包名添加上"classpath*:"的前綴和"**/*.class"的後綴 //最後結果:classpath*:cn/mrdear/**/*.class String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + "/" + this.resourcePattern; //將包下的全部class文件用Resource的方式描述 //Resource--資源描述符 //裏面的實現很是大,有興趣能夠本身看看。 //主要是將packageSearchPath分紅classpath,包名,後綴名三部分進行處理,又根據有無*或者? //等表達式,處理方式有所不一樣 Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); //對每一個class進行處理 for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } //是否非目錄,可讀 if (resource.isReadable()) { try { //這個metadataReader包含class文件中,類上的註解 //方法的註解,所使用註解的元註解等描述 //在獲取metadataReader的同時,在CachingMetadataReaderFactory類的 //metadataReaderCache屬性中存放了一份。此屬性是LinkedHashMap MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource); //2.1.1判斷metadataReader可否經過註解類型過濾器過濾 if (isCandidateComponent(metadataReader)) { //建立bean definition,拿到metadataReader的beanClass //保存metadataReader的annotationMetadata的引用 ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); //取得資源描述符的引用 sbd.setResource(resource); sbd.setSource(resource); //2.1.2查看類是否具體且獨立 if (isCandidateComponent(sbd)) { if (debugEnabled) { //肯定候選組件class logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { //被忽略,不是一個具體的頂層class logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { //被忽略,不匹配任何過濾器 logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( //失敗讀取候選組件 "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { //不可讀,忽略 logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { //掃描類路徑時IO異常 throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } //最後返回候選的bean definition return candidates; }
我這裏返回的就只有兩個類,加了@ControllerAdvice的GlobalException、加了@Service的BookServiceImpl。
其他的要麼是接口,要麼沒被掃描,要麼被過濾器過濾了,如下是我項目中全部class:
跟蹤標記2.1.1的方法
在ClassPathScanningCandidateComponentProvider類中實現
//2.1.1判斷metadataReader可否經過註解類型過濾器過濾 isCandidateComponent(metadataReader) /** * Determine whether the given class does not match any exclude filter * and does match at least one include filter. * * 不匹配任何exclude filter,至少匹配一個include filter. * 才能肯定其爲候選人 */ protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this.excludeFilters) { //2.1.1.1跟蹤match方法 //若是metadataReader中有註解匹配exclude過濾器的註解,則返回false if (tf.match(metadataReader, this.metadataReaderFactory)) { return false; } } for (TypeFilter tf : this.includeFilters) { //若是metadataReader中有註解匹配include過濾器的註解,則進入條件 if (tf.match(metadataReader, this.metadataReaderFactory)) { //2.1.1.2是否有@Conditional註解,進行相關處理 return isConditionMatch(metadataReader); } } return false; }
過濾器中存放的都是AnnotationTypeFilter類型
TypeFilter是其頂層接口
match方法主要是在AbstractTypeHierarchyTraversingFilter抽象類中實現
跟蹤標記2.1.1.1的方法
在AbstractTypeHierarchyTraversingFilter類中實現
//2.1.1.1跟蹤match方法 tf.match(metadataReader, this.metadataReaderFactory) @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { // This method optimizes avoiding unnecessary creation of ClassReaders // as well as visiting over those readers. // 此方法作了優化,避免沒必要要的ClassReaders建立以及對它們的訪問 // matchSelf方法判斷metadataReader中相關class的註解有沒有包含這個過濾器的註解 // 若是沒有,可是過濾器的considerMetaAnnotations屬性設置爲true, // 那麼再判斷class全部註解的元註解中,有沒有包含這個過濾器的註解 // 有就返回true,進入條件 if (matchSelf(metadataReader)) { return true; } ClassMetadata metadata = metadataReader.getClassMetadata(); // 默認返回false,不進入條件 if (matchClassName(metadata.getClassName())) { return true; } //considerInherited這個屬性前面跟蹤的過濾器中都爲false //和過濾器的註解有關,其元註解包含Inherited, //那麼considerInherited屬性就爲true if (this.considerInherited) { if (metadata.hasSuperClass()) { // Optimization to avoid creating ClassReader for super class. Boolean superClassMatch = matchSuperClass(metadata.getSuperClassName()); if (superClassMatch != null) { if (superClassMatch.booleanValue()) { return true; } } else { // Need to read super class to determine a match... try { if (match(metadata.getSuperClassName(), metadataReaderFactory)) { return true; } } catch (IOException ex) { logger.debug("Could not read super class [" + metadata.getSuperClassName() + "] of type-filtered class [" + metadata.getClassName() + "]"); } } } } //considerInterfaces屬性在AnnotationTypeFilter構造器中都默認被設置爲false if (this.considerInterfaces) { for (String ifc : metadata.getInterfaceNames()) { // Optimization to avoid creating ClassReader for super class Boolean interfaceMatch = matchInterface(ifc); if (interfaceMatch != null) { if (interfaceMatch.booleanValue()) { return true; } } else { // Need to read interface to determine a match... try { if (match(ifc, metadataReaderFactory)) { return true; } } catch (IOException ex) { logger.debug("Could not read interface [" + ifc + "] for type-filtered class [" + metadata.getClassName() + "]"); } } } } return false; }
跟蹤標記2.1.1.2的方法
在ClassPathScanningCandidateComponentProvider類中實現
//2.1.1.2是否有@Conditional註解,進行相關處理 isConditionMatch(metadataReader); /** * Determine whether the given class is a candidate component based on any * {@code @Conditional} annotations. * * 肯定指定類是不是基於任何@Conditional註解的候選組件 */ private boolean isConditionMatch(MetadataReader metadataReader) { if (this.conditionEvaluator == null) { this.conditionEvaluator = new ConditionEvaluator(getRegistry(), getEnvironment(), getResourceLoader()); } //跟蹤這個方法 return !this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata()); }
因而進入ConditionEvaluator的shouldSkip方法
/** * Determine if an item should be skipped based on {@code @Conditional} annotations. * The {@link ConfigurationPhase} will be deduced from the type of item (i.e. a * {@code @Configuration} class will be {@link ConfigurationPhase#PARSE_CONFIGURATION}) * * 根據@Conditional註解肯定一個子項是否應該被跳過 * 從子項的類型能夠推導ConfigurationPhase,好比@Configuration class就是 * ConfigurationPhase#PARSE_CONFIGURATION--解析配置 */ public boolean shouldSkip(AnnotatedTypeMetadata metadata) { return shouldSkip(metadata, null); } //這個方法就不跟了,若是要了解condition註解的用法,能夠詳細瞭解該方法 public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase) { //類上註解或者註解上的元註解不包含Conditional註解就返回false if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) { return false; } if (phase == null) { if (metadata instanceof AnnotationMetadata && ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) { return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION); } return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN); } List<Condition> conditions = new ArrayList<Condition>(); for (String[] conditionClasses : getConditionClasses(metadata)) { for (String conditionClass : conditionClasses) { Condition condition = getCondition(conditionClass, this.context.getClassLoader()); conditions.add(condition); } } AnnotationAwareOrderComparator.sort(conditions); for (Condition condition : conditions) { ConfigurationPhase requiredPhase = null; if (condition instanceof ConfigurationCondition) { requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase(); } if (requiredPhase == null || requiredPhase == phase) { if (!condition.matches(this.context, metadata)) { return true; } } } return false; }
跟蹤標記2.1.2的方法
在ClassPathScanningCandidateComponentProvider類中實現
//2.1.2查看類是否具體且獨立 isCandidateComponent(sbd) /** * Determine whether the given bean definition qualifies as candidate. * <p>The default implementation checks whether the class is concrete * (i.e. not abstract and not an interface). Can be overridden in subclasses. * * 肯定bean definition qualifies可否做爲候選 * 默認實現會檢查class是否具體(不是抽象、不是接口)。能夠被子類覆蓋 */ protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { //看下這兩個判斷的含義 return (beanDefinition.getMetadata().isConcrete() && beanDefinition.getMetadata().isIndependent()); } //不能是接口和抽象類 public boolean isConcrete() { return !(this.isInterface || this.isAbstract); } //要麼是頂層class,要麼是被嵌套的class(靜態內部類),可是被嵌套的class必須可以從 //封閉的class中獨立構造,才能說明此class是獨立的。 public boolean isIndependent() { //沒有封閉的class或者是獨立的內部類 return (this.enclosingClassName == null || this.independentInnerClass); }
跟蹤標記2.2的方法
在AnnotationScopeMetadataResolver類中實現
//2.2解析@scope註解 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); /** * Resolve the {@link ScopeMetadata} appropriate to the supplied * bean {@code definition}. * <p>Implementations can of course use any strategy they like to * determine the scope metadata, but some implementations that spring * immediately to mind might be to use source level annotations * present on {@link BeanDefinition#getBeanClassName() the class} of the * supplied {@code definition}, or to use metadata present in the * {@link BeanDefinition#attributeNames()} of the supplied {@code definition}. * * 解析適用於BeanDefinition的ScopeMetadata * 實現固然可使用任何喜歡的策略去肯定scope metadata,可是spring的實現立馬 * 想到的是使用source level註解在BeanDefinition對應的class上 * 或者將metadata存放於BeanDefinition的屬性中 */ public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { //默認單例,無代理 ScopeMetadata metadata = new ScopeMetadata(); if (definition instanceof AnnotatedBeanDefinition) { AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; //拿到指定類上的@scope註解的全部屬性 AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( annDef.getMetadata(), this.scopeAnnotationType); if (attributes != null) { metadata.setScopeName(attributes.getString("value")); ScopedProxyMode proxyMode = attributes.getEnum("proxyMode"); if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) { proxyMode = this.defaultProxyMode; } metadata.setScopedProxyMode(proxyMode); } } return metadata; }
跟蹤標記2.3的方法
在AnnotationBeanNameGenerator類中實現
//2.3AnnotatedBeanDefinition的默認名稱生成規則 String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { if (definition instanceof AnnotatedBeanDefinition) { //先進入這個方法查看 String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition); if (StringUtils.hasText(beanName)) { // Explicit bean name found. // 發現明確bean Name return beanName; } } // Fallback: generate a unique default bean name. // 回退:生成一個惟一的默認beanName return buildDefaultBeanName(definition, registry); } /** * Derive a bean name from one of the annotations on the class. * * 從類上的一個註解中,派生出bean name */ protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) { AnnotationMetadata amd = annotatedDef.getMetadata(); //嘉定拿的是org.springframework.web.bind.annotation.ControllerAdvice Set<String> types = amd.getAnnotationTypes(); String beanName = null; for (String type : types) { //拿到@ControllerAdvice上的全部的屬性 AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type); //將@ControllerAdvice註解名,@ControllerAdvice的元註解,@ControllerAdvice上的屬性 //當作參數傳遞 //進入這個方法 if (isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) { //獲取註解上的value屬性對應的值 Object value = attributes.get("value"); if (value instanceof String) { String strVal = (String) value; if (StringUtils.hasLength(strVal)) { if (beanName != null && !strVal.equals(beanName)) { throw new IllegalStateException("Stereotype annotations suggest inconsistent " + "component names: '" + beanName + "' versus '" + strVal + "'"); } //用value屬性對應的值做爲beanName beanName = strVal; } } } } return beanName; } /** * Check whether the given annotation is a stereotype that is allowed * to suggest a component name through its annotation {@code value()}. * * 檢查註解是否是stereotype類型,若是是的話,能夠用註解的value()屬性,做爲組件名稱 */ protected boolean isStereotypeWithNameValue(String annotationType, Set<String> metaAnnotationTypes, Map<String, Object> attributes) { //註解是否是stereotype類型,主要看他是否是component註解、ManagedBean註解或者Named註解 //或者註解的元註解包含component註解 boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) || (metaAnnotationTypes != null && metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME)) || annotationType.equals("javax.annotation.ManagedBean") || annotationType.equals("javax.inject.Named"); //是stereotype類型,且有value屬性的註解,返回true return (isStereotype && attributes != null && attributes.containsKey("value")); }
上面看了beanDefinition是AnnotatedBeanDefinition類型狀況下,beanName怎樣生成。可是若是class上的stereotype註解,沒有給value屬性賦值,那麼又是怎樣生成beanName的?
查看其默認的beanName生成方式:
buildDefaultBeanName(definition, registry);
此方法的實現仍是在AnnotationBeanNameGenerator類中:
/** * Derive a default bean name from the given bean definition. * <p>The default implementation delegates to {@link #buildDefaultBeanName(BeanDefinition)}. * * 從給定的bean definition派生一個默認bean Name */ protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { return buildDefaultBeanName(definition); } /** * Derive a default bean name from the given bean definition. * <p>The default implementation simply builds a decapitalized version * of the short class name: e.g. "mypackage.MyJdbcDao" -> "myJdbcDao". * <p>Note that inner classes will thus have names of the form * "outerClassName.InnerClassName", which because of the period in the * name may be an issue if you are autowiring by name. * * 默認的實現是構建一個首字母小寫(像變量同樣的命名方式)的簡短類名。 * 注意內部類所以會是這樣的格式"outerClassName.InnerClassName" * 若是經過名稱自動注入,中間的點就可能引起問題 */ protected String buildDefaultBeanName(BeanDefinition definition) { //cn.mrdear.exception.GlobalException => GlobalException String shortClassName = ClassUtils.getShortName(definition.getBeanClassName()); //此方法將字符串首字符大寫轉小寫,可是若是第二個字符也是大寫就不進行轉換,由於他多是 //這樣的格式--> "URL" return Introspector.decapitalize(shortClassName); }
跟蹤標記2.4的方法
在ClassPathBeanDefinitionScanner類中實現
//2.4給beanDefinition設置默認值,自動注入的候選者 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); /** * Apply further settings to the given bean definition, * beyond the contents retrieved from scanning the component class. * * 除從組件class掃描檢索的內容外,應用更多的設置到bean definition */ protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) { //掃描器中的Defaults應用到beanDefinition中 beanDefinition.applyDefaults(this.beanDefinitionDefaults); if (this.autowireCandidatePatterns != null) { //設置自動注入候選者 beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName)); } }
跟蹤標記2.5的方法
在AnnotationConfigUtils類中實現
//2.5拿到類上其餘的context名稱空間的註解,若是有的話,獲取其value屬性 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) { processCommonDefinitionAnnotations(abd, abd.getMetadata()); } static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { //類上是否有Lazy註解,或者註解的元註解上有Lazy註解 if (metadata.isAnnotated(Lazy.class.getName())) { //拿到@Lazy註解上的全部屬性,獲取其value屬性的值 abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value")); } //metadata不屬於abd的狀況 else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) { abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value")); } //類上是否有Primary註解,或者註解的元註解上有Primary註解 if (metadata.isAnnotated(Primary.class.getName())) { abd.setPrimary(true); } //類上是否有DependsOn註解,或者註解的元註解上有DependsOn註解 if (metadata.isAnnotated(DependsOn.class.getName())) { //拿到@DependsOn註解上的全部屬性,獲取其value屬性的值 abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value")); } if (abd instanceof AbstractBeanDefinition) { AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd; //類上是否有Role註解,或者註解的元註解上有Role註解 if (metadata.isAnnotated(Role.class.getName())) { //拿到@Role註解上的全部屬性,獲取其value屬性的值 absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue()); } //類上是否有Description註解,或者註解的元註解上有Role註解 if (metadata.isAnnotated(Description.class.getName())) { //拿到@Description註解上的全部屬性,獲取其value屬性的值 absBd.setDescription(attributesFor(metadata, Description.class).getString("value")); } } }
跟蹤標記2.6的方法
在ClassPathBeanDefinitionScanner類中實現
//2.6檢查beanName是否正確匹配對應的bean Definition,該名稱是否已經被註冊 checkCandidate(beanName, candidate) protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException { //工廠中沒有註冊這個beanName,返回true if (!this.registry.containsBeanDefinition(beanName)) { return true; } BeanDefinition existingDef = this.registry.getBeanDefinition(beanName); BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition(); if (originatingDef != null) { existingDef = originatingDef; } //若是已存在的和入參的beanDefinition可以兼容,就返回false,不然拋出異常 if (isCompatible(beanDefinition, existingDef)) { return false; } throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName + "' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " + "non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]"); }
跟蹤標記3的方法
此方法在ComponentScanBeanDefinitionParser類中實現
// 3. 註冊組件 registerComponents(parserContext.getReaderContext(), beanDefinitions, element); protected void registerComponents( XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) { //這裏返回的是null Object source = readerContext.extractSource(element); //拿到組合組件定義對象,以完整標籤名作爲name CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source); for (BeanDefinitionHolder beanDefHolder : beanDefinitions) { //分兩部分看 //3.1bean組件定義的構造初始化 //將建立好的BeanComponentDefinition放入到組合組件定義的nestedComponents中 //nestedComponents是一個LinkedList compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder)); } // Register annotation config processors, if necessary. // 若是必要的話,註冊註解配置處理器 boolean annotationConfig = true; //拿到component-scan標籤的annotation-config屬性 if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) { //默認設置爲true annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE)); } if (annotationConfig) { //3.2查看怎麼註冊註解配置處理器 Set<BeanDefinitionHolder> processorDefinitions = AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source); for (BeanDefinitionHolder processorDefinition : processorDefinitions) { //若是有爲被註冊的處理器,註冊完成後再添加到組合組件定義中 compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition)); } } //這裏空實現 readerContext.fireComponentRegistered(compositeDef); }
跟蹤標記3.1的方法
進入BeanComponentDefinition的構造方法
//3.1bean組件定義的構造初始化 new BeanComponentDefinition(beanDefHolder) public BeanComponentDefinition(BeanDefinitionHolder holder) { //先看父類構造作了什麼操做 super(holder); //找到這個class中,屬性爲註冊到工廠中的bean deifiniion或者BeanReference的集合 findInnerBeanDefinitionsAndBeanReferences(holder.getBeanDefinition()); } /** * 其實BeanComponentDefinition就是BeanDefinitionHolder的子類 * * Copy constructor: Create a new BeanDefinitionHolder with the * same contents as the given BeanDefinitionHolder instance. * <p>Note: The wrapped BeanDefinition reference is taken as-is; * it is {@code not} deeply copied. * * 複製構造:利用給定的beanDefinitionHolder實例,建立一個新的BeanDefinitionHolder */ public BeanDefinitionHolder(BeanDefinitionHolder beanDefinitionHolder) { Assert.notNull(beanDefinitionHolder, "BeanDefinitionHolder must not be null"); this.beanDefinition = beanDefinitionHolder.getBeanDefinition(); this.beanName = beanDefinitionHolder.getBeanName(); this.aliases = beanDefinitionHolder.getAliases(); }
而後再瞭解下findInnerBeanDefinitionsAndBeanReferences方法作了什麼事情
private void findInnerBeanDefinitionsAndBeanReferences(BeanDefinition beanDefinition) { List<BeanDefinition> innerBeans = new ArrayList<BeanDefinition>(); List<BeanReference> references = new ArrayList<BeanReference>(); PropertyValues propertyValues = beanDefinition.getPropertyValues(); //拿到類中全部的屬性值,若是屬性爲在bean工廠中註冊的bean definition、或者 //有BeanReference--非實體bean只是邏輯上的引用,則放入集合 for (int i = 0; i < propertyValues.getPropertyValues().length; i++) { PropertyValue propertyValue = propertyValues.getPropertyValues()[i]; Object value = propertyValue.getValue(); if (value instanceof BeanDefinitionHolder) { innerBeans.add(((BeanDefinitionHolder) value).getBeanDefinition()); } else if (value instanceof BeanDefinition) { innerBeans.add((BeanDefinition) value); } else if (value instanceof BeanReference) { references.add((BeanReference) value); } } this.innerBeanDefinitions = innerBeans.toArray(new BeanDefinition[innerBeans.size()]); this.beanReferences = references.toArray(new BeanReference[references.size()]); }
跟蹤標記3.2的方法
進入AnnotationConfigUtils的構造方法
//3.2查看怎麼註冊註解配置處理器 Set<BeanDefinitionHolder> processorDefinitions = AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source); /** * Register all relevant annotation post processors in the given registry. * * 註冊全部相關的註解後處理器到指定工廠中 */ public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, Object source) { DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { //bean工廠的依賴比較器不是AnnotationAwareOrderComparator的實例, //就換成AnnotationAwareOrderComparator if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } //bean工廠的自動注入候選解析器不是ContextAnnotationAutowireCandidateResolver的實例, //就換成ContextAnnotationAutowireCandidateResolver if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4); //工廠中沒有註冊internalConfigurationAnnotationProcessor,則註冊 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)); } //工廠中沒有註冊internalAutowiredAnnotationProcessor,則註冊 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)); } //工廠中沒有註冊internalRequiredAnnotationProcessor,則註冊 if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor. // 檢查是否支持JSR-250,若是有則添加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. // 檢查JPA支持,若是有則添加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)); } //工廠中沒有註冊internalEventListenerProcessor,則註冊 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)); } //工廠中沒有註冊internalEventListenerFactory,則註冊 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; }
到這裏也就跟蹤完了。
其實還有不少種狀況沒有分析,只能先把握總體的脈絡,遇到具體的狀況再作具體分析。
context:component-scan
上的base-package
屬性,有佔位符的進行解析,並切分爲數組形式——————————————————————————————————
Component
。context:exclude-filter
和context:exclude-filter
,根據子標籤上的 type 屬性建立不一樣的類型過濾器。並添加到掃描器的 excludeFilters 屬性或 includeFilters 屬性中。——————————————————————————————————
base-package
,經過base-package
獲取 Resource 對象數組,對符合條件的 Resource 組裝成 BeanDefinition ,並將 BeanDefinition 集合返回。條件:不匹配 excludeFilters 中的過濾器,匹配 includeFilters 的過濾器的同時,若是有@Conditional
註解須要知足限制。@Scope
等註解以及元註解,設置屬性——————————————————————————————————