SPRing context命名空間有property-placeholder、property-override、annotation-config、component-scan、load-time-weaver、spring-configured、mbean-export和mbean-server 8個(gè)標(biāo)簽。
property-placeholder和property-override標(biāo)簽的解析見(jiàn)property-placeholder和property-override標(biāo)簽的解析,annotation-config標(biāo)簽的解析見(jiàn)解析context命名空間之a(chǎn)nnotation-config標(biāo)簽。這一節(jié)來(lái)探討component-scan標(biāo)簽的解析與用途。
component-scan標(biāo)簽擁有同annotation-config標(biāo)簽一樣的作用,但它比annotation-config標(biāo)簽更強(qiáng)大。annotation-config標(biāo)簽主要作用是注冊(cè)后處理來(lái)對(duì)已創(chuàng)建的BeanDefintion對(duì)象和實(shí)例化的bean做加工,component-scan標(biāo)簽作用不僅于此,還可以把特定包下被指定注解類標(biāo)注的類對(duì)象封裝成BeanDefinition對(duì)象并注冊(cè)到BeanDefinitionRegistry對(duì)象中,這樣大大簡(jiǎn)化了xml文件的內(nèi)容。
component-scan標(biāo)簽的解析器類為ComponentScanBeanDefinitionParser類,它直接實(shí)現(xiàn)了BeanDefinitionParser接口,下面是它實(shí)現(xiàn)的parse方法的源代碼。
@Override public BeanDefinition parse(Element element, ParserContext parserContext) { String basePackage = element.getAttribute("base-package"); // 處理base-package屬性值中被“${”、“}”包圍的變量 // 比如,base-package="${package}",如果上下文環(huán)境對(duì)象中有一個(gè)Properties對(duì)象的key為package // ->那么,base-package的值就為這個(gè)key對(duì)應(yīng)的value值 basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); // 如果有多個(gè)根包需要掃描,那么以“,; /t/n”中的一個(gè)隔開(kāi) String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,",; /t/n"); // Actually scan for bean definitions and register them. // 創(chuàng)建ClassPathBeanDefinitionScanner對(duì)象,這個(gè)對(duì)象用于掃描base-package指定的包下面的類對(duì)象 // ->并把匹配的類對(duì)象使用BeanDefinition對(duì)象封裝,然后注冊(cè)到BeanDefinitionRegistry中 ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); // 注冊(cè)ComponentDefinition和注解配置處理器(和annotation-config標(biāo)簽的一樣) registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }ComponentScanBeanDefinitionParser的parser方法,首先創(chuàng)建并初始化ClassPathBeanDefinitionScanner對(duì)象;然后使用前面scanner對(duì)象掃描指定包下匹配的類對(duì)象并注冊(cè)相應(yīng)BeanDefinition對(duì)象;最后調(diào)用registerComponents方法,如果屬性annotation-config的值為true,則同annotation-config標(biāo)簽一樣會(huì)注冊(cè)處理注解配置的各種后處理器。我們先看看最后一步中的registerComponents方法,后面我們?cè)趤?lái)詳細(xì)探討spring如何掃描和匹配包下的類對(duì)象。
protected void registerComponents( XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) { Object source = readerContext.extractSource(element); CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source); for (BeanDefinitionHolder beanDefHolder : beanDefinitions) { compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder)); } // Register annotation config processors, if necessary. boolean annotationConfig = true; if (element.hasAttribute("annotation-config")) { annotationConfig = Boolean.valueOf(element.getAttribute("annotation-config")); } if (annotationConfig) { Set<BeanDefinitionHolder> processorDefinitions = AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source); for (BeanDefinitionHolder processorDefinition : processorDefinitions) { compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition)); } } readerContext.fireComponentRegistered(compositeDef); }registerComponents方法代碼很簡(jiǎn)單,它主要是拿去component-scan標(biāo)簽的annotation-config屬性值,這個(gè)屬性值默認(rèn)為true的,如果annotation-config值為true,則注冊(cè)注解配置的各個(gè)處理器,這個(gè)注冊(cè)過(guò)程在上一節(jié)——“解析annotation-config標(biāo)簽”中已經(jīng)探討了,這里就不用再說(shuō)了。
這一節(jié)我們?cè)敿?xì)討論spring如何使用component-scan標(biāo)簽來(lái)掃描和匹配包下的類對(duì)象。
(1)創(chuàng)建并初始化ClassPathBeanDefinitionScanner對(duì)象 ComponentScanBeanDefinitionParser的parser方法調(diào)用configureScanner(ParserContext parserContext, Element element)方法來(lái)創(chuàng)建初始化并返回一個(gè)ClassPathBeanDefinitionScanner對(duì)象,這個(gè)方法的源碼如下。
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { // 設(shè)置是否自動(dòng)檢測(cè)被@Component、@Repository、@Service或者@Controller注解標(biāo)注的類 // 默認(rèn)為true。如果為false,那么上面4個(gè)注解將沒(méi)有作用,因此一般都不會(huì)設(shè)置這個(gè)屬性 boolean useDefaultFilters = true; if (element.hasAttribute("use-default-filters")) { useDefaultFilters = Boolean.valueOf(element.getAttribute("use-default-filters")); } // 把注冊(cè)BeanDefinition的任務(wù)委托給scanner ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters); scanner.setResourceLoader(parserContext.getReaderContext().getResourceLoader()); scanner.setEnvironment(parserContext.getReaderContext().getEnvironment()); // 讓scanner持有component-scan標(biāo)簽的父節(jié)點(diǎn)<beans>的屬性默認(rèn)值 scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults()); scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns()); // 設(shè)置資源匹配模式,默認(rèn)為**/*.class if (element.hasAttribute("resource-pattern")) { scanner.setResourcePattern(element.getAttribute("resource-pattern")); } try { // 設(shè)置Bean名稱生成器 parseBeanNameGenerator(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } try { // 設(shè)置作用域 parseScope(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } // 設(shè)置過(guò)濾器,即用于指定哪些類需要被處理,哪些類需要被忽略 parseTypeFilters(element, scanner, parserContext); return scanner; }configureScanner方法有4步,第一步是調(diào)用createScanner方法來(lái)創(chuàng)建一個(gè)ClassPathBeanDefinitionScanner 對(duì)象,并使用ParserContext對(duì)象來(lái)初始化它;第二步是調(diào)用parseBeanNameGenerator方法;第三步是調(diào)用parseScope方法,第四步是調(diào)用parseTypeFilters方法。下面我們分別介紹這4個(gè)方法。
1)調(diào)用createScanner方法創(chuàng)建ClassPathBeanDefinitionScanner 對(duì)象,代碼如下。
/** * 創(chuàng)建并返回ClassPathBeanDefinitionScanner對(duì)象 **/ protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) { return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters); }2)調(diào)用parseBeanNameGenerator方法設(shè)置Bean名稱生成器
protected void parseBeanNameGenerator(Element element, ClassPathBeanDefinitionScanner scanner) { if (element.hasAttribute("name-generator")) { // 生成一個(gè)BeanNameGenerator對(duì)象 BeanNameGenerator beanNameGenerator = (BeanNameGenerator) instantiateUserDefinedStrategy( element.getAttribute("name-generator"), BeanNameGenerator.class, scanner.getResourceLoader().getClassLoader()); scanner.setBeanNameGenerator(beanNameGenerator); } }parseBeanNameGenerator為scanner對(duì)象設(shè)置一個(gè)BeanNameGenerator接口對(duì)象。spring提供了兩個(gè)這樣的對(duì)象,其一是AnnotationBeanNameGenerator,它被用于獲取被@Component等注解的類對(duì)象的bean名稱。其二是DefaultBeanNameGenerator,它被用于獲取一般bean的名稱。
生成BeanNameGenerator對(duì)象調(diào)用了ClassPathBeanDefinitionScanner類的私有方法instantiateUserDefinedStrategy,這個(gè)方法用于實(shí)例化一個(gè)指定類型的對(duì)象,源碼如下。
/** * 根據(jù)指定的class名稱實(shí)例化一個(gè)對(duì)象,這個(gè)對(duì)象必須為指定的strategyType類型。 **/ private Object instantiateUserDefinedStrategy(String className, Class<?> strategyType, ClassLoader classLoader) { Object result; try { result = classLoader.loadClass(className).newInstance(); } catch (ClassNotFoundException ex) { throw new IllegalArgumentException("Class [" + className + "] for strategy [" + strategyType.getName() + "] not found", ex); } catch (Exception ex) { throw new IllegalArgumentException("Unable to instantiate class [" + className + "] for strategy [" + strategyType.getName() + "]: a zero-argument constructor is required", ex); } if (!strategyType.isAssignableFrom(result.getClass())) { throw new IllegalArgumentException("Provided class name must be an implementation of " + strategyType); } return result; }3)調(diào)用parseScope方法設(shè)置作用域解析器或者作用域的默認(rèn)代理模式
protected void parseScope(Element element, ClassPathBeanDefinitionScanner scanner) { // 如果scope-resolver有值,則注冊(cè)ScopeMetadataResolver if (element.hasAttribute("scope-resolver")) { if (element.hasAttribute("scoped-proxy")) { throw new IllegalArgumentException( "Cannot define both 'scope-resolver' and 'scoped-proxy' on <component-scan> tag"); } ScopeMetadataResolver scopeMetadataResolver = (ScopeMetadataResolver) instantiateUserDefinedStrategy( element.getAttribute("scope-resolver"), ScopeMetadataResolver.class, scanner.getResourceLoader().getClassLoader()); scanner.setScopeMetadataResolver(scopeMetadataResolver); } // 設(shè)置作用域的默認(rèn)代理模式ScopedProxyMode if (element.hasAttribute("scoped-proxy")) { String mode = element.getAttribute("scoped-proxy"); 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'"); } } }注:scope-resolver和scoped-proxy不能同時(shí)定義。
4)調(diào)用parseTypeFilters方法設(shè)置類型過(guò)濾器 parseTypeFilters方法主要是用來(lái)component-scan標(biāo)簽的include-filter和exclude-filter子節(jié)點(diǎn)。include-filter標(biāo)簽用來(lái)表示必須包含的類,不管這個(gè)類是否被默認(rèn)的注解類標(biāo)注。exclude-filter標(biāo)簽用來(lái)表示掃描時(shí)必須忽略的類,即使這個(gè)類被默認(rèn)的注解標(biāo)注了。但include-filter和exclude-filter兩個(gè)元素不能共存。
protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) { // 解析exclude和include過(guò)濾器元素 ClassLoader classLoader = scanner.getResourceLoader().getClassLoader(); NodeList nodeList = element.getChildNodes(); // 遍歷component-scan標(biāo)簽下的子節(jié)點(diǎn) 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 { if ("include-filter".equals(localName)) { // 解析include元素 TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext); scanner.addIncludeFilter(typeFilter); } else if ("exclude-filter".equals(localName)) { 解析exclude元素 TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext); scanner.addExcludeFilter(typeFilter); } } catch (Exception ex) { parserContext.getReaderContext().error( ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } } } }parseTypeFilters方法首先判斷區(qū)分出include-filter和exclude-filter標(biāo)簽,然后調(diào)用createTypeFilter方法來(lái)解析他們并返回TypeFilter,scanner把他們的指代的TypeFilter對(duì)象保存到它的includeFilters和excludeFilters列表中。
/** * 解析component-scan標(biāo)簽的include-filter和exclude-filter子節(jié)點(diǎn),并返回TypeFilter對(duì)象 **/ protected TypeFilter createTypeFilter(Element element, ClassLoader classLoader, ParserContext parserContext) { String filterType = element.getAttribute("type"); String expression = element.getAttribute("expression"); expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression); try { if ("annotation".equals(filterType)) { // 指定過(guò)濾的注解。expression=類全名稱 return new AnnotationTypeFilter((Class<Annotation>) classLoader.loadClass(expression)); } else if ("assignable".equals(filterType)) { // 指定過(guò)濾的類,它的子類或者實(shí)現(xiàn)類也包括。expression=類全名稱 return new AssignableTypeFilter(classLoader.loadClass(expression)); } else if ("aspectj".equals(filterType)) { // 指定aspectj表達(dá)式來(lái)過(guò)濾類。expression=aspectj表達(dá)式字符串 return new AspectJTypeFilter(expression, classLoader); } else if ("regex".equals(filterType)) { // 通過(guò)指定的正則表達(dá)式來(lái)過(guò)濾類。expression=正則表達(dá)式字符串 return new RegexPatternTypeFilter(Pattern.compile(expression)); } else if ("custom".equals(filterType)) { // 用戶自定義過(guò)濾器類型 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); } }(2)使用ClassPathBeanDefinitionScanner對(duì)象的doScan(String… basePackages)方法開(kāi)始掃描包,這個(gè)方法的源碼如下。
protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>(); // 遍歷指定的包 for (String basePackage : basePackages) { // 獲取包下的所有候選BeanDefinition對(duì)象 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); // 遍歷所有候選BeanDefinition對(duì)象 for (BeanDefinition candidate : candidates) { // 獲取一個(gè)ScopeMetadata對(duì)象,默認(rèn)為AnnotationScopeMetadataResolver // 如果目標(biāo)類未被@Scope注解,則返回一個(gè)默認(rèn)的ScopeMetadata ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); // 使用bean名稱生成器生成bean名稱,默認(rèn)生成器為AnnotationBeanNameGenerator // 首先是以注解的value為bean名稱,如果注解的value沒(méi)有值,則使用默認(rèn)的名稱 String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { // 進(jìn)一步處理BeanDefinition對(duì)象,比如,bean是否可以被用于自動(dòng)注入的備選bean postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { // 處理定義在目標(biāo)類上的注解,包括@Lazy, @Primary, @DependsOn, @Role, @Description AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } // 檢查beanName是否已經(jīng)存在BeanDefinitionRegistry中存在 if (checkCandidate(beanName, candidate)) { // beanName還沒(méi)被使用過(guò) BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); // 如果有必要,則創(chuàng)建作用域代理 // 如果創(chuàng)建了代理,則返回表示代理對(duì)象的BeanDefinitionHolder definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); // 注冊(cè)BeanDefinitionHolder對(duì)象 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }關(guān)于doScan方法所調(diào)用的方法,我只探討其中的三個(gè),其一是ClassPathBeanDefinitionScanner的findCandidateComponents方法;其二是AnnotationConfigUtils的processCommonDefinitionAnnotations靜態(tài)方法;其三是AnnotationConfigUtils的applyScopedProxyMode靜態(tài)方法。
1) findCandidateComponents方法繼承自ClassPathScanningCandidateComponentProvider類,是用于查找指定包及其子包下所有匹配的類,并返回這些類對(duì)應(yīng)的BeanDefinition對(duì)象。它的源碼如下。
public Set<BeanDefinition> findCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>(); try { // 聲明有CLASSPATH_ALL_URL_PREFIX="classpath*:" // resourcePattern默認(rèn)為"**/*.class" String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + "/" + this.resourcePattern; // 根據(jù)模式匹配來(lái)搜索包下面匹配的所有類 // 默認(rèn)的ResourcePatternResolver實(shí)現(xiàn)類為PathMatchingResourcePatternResolver類 Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); // 遍歷所有匹配的類 for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { // 默認(rèn)的MetadataReaderFactory實(shí)現(xiàn)類為CachingMetadataReaderFactory // 默認(rèn)返回的是SimpleMetadataReader對(duì)象 MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource); // 通過(guò)過(guò)濾器來(lái)判斷類對(duì)象是否為候選類 if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); // 候選類必須是一個(gè)具體的實(shí)現(xiàn)類,并且它的實(shí)例化必須是獨(dú)立的 if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { 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) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; }findCandidateComponents方法首先獲取指定包及其子包下所有類的資源對(duì)象,然后使用CachingMetadataReaderFactory對(duì)象獲取一個(gè)SimpleMetadataReader的MetadataReader對(duì)象,SimpleMetadataReader使用ClassReader對(duì)象從Resource對(duì)象持有的類文件輸入流中讀取類信息,ClassReader允許通過(guò)ClassVisitor對(duì)象來(lái)訪問(wèn)它持有的類信息。而SimpleMetadataReader使用AnnotationMetadataReadingVisitor訪問(wèn)器把ClassReader存有的類信息分解成類元數(shù)據(jù)ClassMetadata對(duì)象和注解元數(shù)據(jù)AnnotationMetadata對(duì)象。 因此findCandidateComponents方法才可以調(diào)用isCandidateComponent(MetadataReader metadataReader)方法來(lái)通過(guò)過(guò)濾器判斷當(dāng)前類是否會(huì)被排除在候選類之外,下面是isCandidateComponent方法的源碼。
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { // 首先使用excludeFilters中的過(guò)濾器檢查當(dāng)前類是否應(yīng)該排除 // 通過(guò)exclude-filter標(biāo)簽配置 for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return false; } } // 最后使用includeFilters來(lái)查看當(dāng)前類是否候選類 // 通過(guò)include-filter標(biāo)簽配置。 // 默認(rèn)為注解類型的過(guò)濾器,注解類為spring定義的@Component for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return isConditionMatch(metadataReader); } } return false; }如果當(dāng)前類是候選類,那么為當(dāng)前類生成一個(gè)ScannedGenericBeanDefinition對(duì)象,ScannedGenericBeanDefinition繼承自GenericBeanDefinition并實(shí)現(xiàn)了AnnotatedBeanDefinition接口。 如果類不是一個(gè)具體且獨(dú)立的類,比如抽象類、接口或者非靜態(tài)內(nèi)部類,通過(guò)反射實(shí)例化一個(gè)對(duì)象的時(shí)候是會(huì)拋出異常的。因此spring還會(huì)判斷一次,在findCandidateComponents方法中調(diào)用isCandidateComponent(AnnotatedBeanDefinition beanDefinition)方法,它的源碼如下。
/** * 判斷類是否是一個(gè)具體類,并且是一個(gè)可以獨(dú)立實(shí)例化的類。 **/ protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { return (beanDefinition.getMetadata().isConcrete() && beanDefinition.getMetadata().isIndependent()); }通過(guò)以上判斷排除,最終獲得一個(gè)ScannedGenericBeanDefinition對(duì)象。現(xiàn)在我們第2點(diǎn)ClassPathBeanDefinitionScanner類的 doScan(String… basePackages)方法拿到這個(gè)對(duì)象后通過(guò)調(diào)用AnnotationConfigUtils工具類processCommonDefinitionAnnotations靜態(tài)方法還做了些什么。
2) AnnotationConfigUtils的processCommonDefinitionAnnotations靜態(tài)方法的源碼如下。
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) { processCommonDefinitionAnnotations(abd, abd.getMetadata()); }processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd)方法把解析類上的注解任務(wù)轉(zhuǎn)交給它的另一個(gè)重載方法processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata),這是一個(gè)只有包訪問(wèn)權(quán)限的靜態(tài)方法,源碼如下。
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { // 解析@Lazy注解,設(shè)置是否延遲加載 if (metadata.isAnnotated(Lazy.class.getName())) { abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value")); } else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) { abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value")); } // 解析@Primary注解 if (metadata.isAnnotated(Primary.class.getName())) { abd.setPrimary(true); } // 解析@DependOn注解 if (metadata.isAnnotated(DependsOn.class.getName())) { abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value")); } if (abd instanceof AbstractBeanDefinition) { AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd; // 解析@Role注解 if (metadata.isAnnotated(Role.class.getName())) { absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue()); } // 解析@Description注解 if (metadata.isAnnotated(Description.class.getName())) { absBd.setDescription(attributesFor(metadata, Description.class).getString("value")); } } }3) doScan(String… basePackages)方法還調(diào)用AnnotationConfigUtils工具類的applyScopedProxyMode靜態(tài)方法,這也是一個(gè)只有包訪問(wèn)權(quán)限的方法,它主要是處理標(biāo)注在類上的@Scope注解,源碼如下。
static BeanDefinitionHolder applyScopedProxyMode( ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) { ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode(); if (scopedProxyMode.equals(ScopedProxyMode.NO)) { // 不需要代理模式 return definition; } boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS); // 創(chuàng)建一個(gè)scope代理 return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); }ScopedProxyCreator類的createScopedProxy靜態(tài)方法源碼如下
public static BeanDefinitionHolder createScopedProxy( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) { // 調(diào)用ScopedProxyUtils工具類的createScopedProxy方法 return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass); }工具類ScopedProxyUtils的createScopedProxy靜態(tài)方法源碼如下。
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition, BeanDefinitionRegistry registry, boolean proxyTargetClass) { String originalBeanName = definition.getBeanName(); BeanDefinition targetDefinition = definition.getBeanDefinition(); // targetBeanName格式為scopedTarget. + originalBeanName String targetBeanName = getTargetBeanName(originalBeanName); // Create a scoped proxy definition for the original bean name, // "hiding" the target bean in an internal target definition. // 創(chuàng)建一個(gè)ScopedProxyFactoryBean類對(duì)應(yīng)BeanDefinition對(duì)象 RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class); proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName)); proxyDefinition.setOriginatingBeanDefinition(targetDefinition); proxyDefinition.setSource(definition.getSource()); proxyDefinition.setRole(targetDefinition.getRole()); proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName); if (proxyTargetClass) { targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); } else { // 設(shè)置為根據(jù)接口做做代理 proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE); } // 根據(jù)代理目標(biāo)BeanDefinition設(shè)置是否可以為自動(dòng)注入的候選bean proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate()); proxyDefinition.setPrimary(targetDefinition.isPrimary()); if (targetDefinition instanceof AbstractBeanDefinition) { proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition); } // 隱藏被代理的bean targetDefinition.setAutowireCandidate(false); targetDefinition.setPrimary(false); // 注冊(cè)被代理的bean的BeanDefinition對(duì)象 registry.registerBeanDefinition(targetBeanName, targetDefinition); // 返回代理bean的BeanDefinitionHolder對(duì)象 return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases()); }(1)component-scan不只是擁有annotation-config的作用,它還用于掃描注冊(cè)指定包下特定的bean。因此,在xml配置文件中定義了component-scan就不需要再定義annotation-config。
(2)component-scan大大簡(jiǎn)化了我們的xml配置。如果我們需要把一個(gè)對(duì)象托管給Spring容器,只需要在類上添加@Component注解或者被@Component標(biāo)注的注解(比如,@Controller、@Service、@Repository)
(3)component-scan的兩個(gè)子標(biāo)簽include-filter和exclude-filter不能共存。這個(gè)并不是從spring的java源碼中體現(xiàn)的,而是在schema文件中體現(xiàn)的。(spring為什么這樣設(shè)計(jì),我實(shí)在是不懂的了)
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注