Spring ioc容器啟動流程—obtainFreshBeanFactory
本文以XmlWebApplicationContext啟動為例說明spring ioc容器啟動流程。
obtainFreshBeanFactory的主要工作是建立DefaultListableBeanFactory例項,解析xml配置檔案,註冊bean。
工作流程概覽
obtainFreshBeanFactory的主要工作在AbstractRefreshableApplicationContext類中refreshBeanFactory方法中完成,這裡完成DefaultListableBeanFactory的建立及初始化,之後在XmlWebApplicationContext類中的loadBeanDefinitions(DefaultListableBeanFactory beanFactory)方法中將bean的load工作轉交給XmlBeanDefinitionReader。
核心工作流程
建立DefaultListableBeanFactory
AbstractRefreshableApplicationContext.java
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
解析xml配置檔案,即loadBeanDefinitions
資源形式的轉化過程
xml配置檔案中的<bean>元素最終會解析例項化為BeanDefinition,註冊到DefaultListableBeanFactory。
configLocation到Resource
利用resourceLoader屬性讀取相應的locationPattern為Resource:
InputSource到Document
先對Resource的資源模式進行校驗,是.xsd還是.dtd方式解析等,XmlBeanDefinitionReader的屬性documentLoader(其為DefaultDocumentLoader型別)載入InputSource為Document,這裡關鍵步驟是用ResourceEntityResolver定位到xsd資源來幫助解析xml檔案:
Document到Element
XmlBeanDefinitionReader建立DefaultBeanDefinitionDocumentReader例項,將解析工作交給它,DefaultBeanDefinitionDocumentReader初步解析Document,獲取根Element,建立BeanDefinitionParserDelegate例項,將解析Element分為兩大類:DefaultElement、CustomElement,其中DefaultElement包括<import>、<alias>、<bean>、巢狀的<beans>,其餘的都為CustomElement:
DefaultBeanDefinitionDocumentReader解析Element過程中,利用代理模式,將解析工作委託給BeanDefinitionParserDelegate進行:
DefaultBeanDefinitionDocumentReader.java
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) { // Element的namespaceURI為空或為"http://www.springframework.org/schema/beans"
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) { // 迴圈遍歷所有Element元素的下一級
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) { // 是否為預設的namespaceUri
parseDefaultElement(ele, delegate); // 處理預設的namespaceUri Element
}
else {
delegate.parseCustomElement(ele); // 處理Custom Element
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
解析預設的Element
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { // 解析import Element
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { // 解析alias Element
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // 解析bean Element
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // 解析內嵌beans Element
// recurse
doRegisterBeanDefinitions(ele);
}
}
解析<import>:
protected void importBeanDefinitionResource(Element ele) {
String location = ele.getAttribute(RESOURCE_ATTRIBUTE); // 獲取import element的resource屬性
if (!StringUtils.hasText(location)) {
getReaderContext().error("Resource location must not be empty", ele);
return;
}
// Resolve system properties: e.g. "${user.dir}"
location = environment.resolveRequiredPlaceholders(location);
Set<Resource> actualResources = new LinkedHashSet<Resource>(4);
// Discover whether the location is an absolute or relative URI
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
}
catch (URISyntaxException ex) {
// cannot convert to an URI, considering the location relative
// unless it is the well-known Spring prefix "classpath*:"
}
// Absolute or relative?
if (absoluteLocation) { // location是否為絕對路徑
try {
int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
}
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
}
}
else {
// No URL -> considering resource location as relative to the current file.
try {
int importCount;
Resource relativeResource = getReaderContext().getResource().createRelative(location);
if (relativeResource.exists()) {
importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource); // 載入import指定的xml配置檔案
actualResources.add(relativeResource);
}
else {
String baseLocation = getReaderContext().getResource().getURL().toString();
importCount = getReaderContext().getReader().loadBeanDefinitions(
StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
}
}
catch (IOException ex) {
getReaderContext().error("Failed to resolve current resource location", ele, ex);
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
ele, ex);
}
}
Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
解析<bean>:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); // 解析Element為BeanDefinition
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 將BeanDefinition註冊到DefaultListableBeanFactory的beanDefinitionMap中
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 傳送Component註冊的訊息
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
BeanDefinitionParserDelegate.java
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE); // 獲取bean的id屬性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);// 獲取bean的name屬性
List<String> aliases = new ArrayList<String>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
// 這裡解析Element為GenericBeanDefinition
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); // 獲取bean element的class屬性
}
try {
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
// 利用反射例項化bean為GenericBeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 解析Element中對應配置檔案的屬性,set到GenericBeanDefinition中
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
parseMetaElements(ele, bd);
parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); // 解析Override方法
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
parseConstructorArgElements(ele, bd); // 解析建構函式引數
parsePropertyElements(ele, bd);
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
// 利用反射例項化GenericBeanDefinition
protected AbstractBeanDefinition createBeanDefinition(String className, String parentName)
throws ClassNotFoundException {
return BeanDefinitionReaderUtils.createBeanDefinition(
parentName, className, this.readerContext.getBeanClassLoader());
}
// 解析Element對應的配置檔案屬性,設定到GenericBeanDefinition
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
BeanDefinition containingBean, AbstractBeanDefinition bd) {
if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
// Spring 2.x "scope" attribute
bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
error("Specify either 'scope' or 'singleton', not both", ele);
}
}
else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
// Spring 1.x "singleton" attribute
bd.setScope(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)) ?
BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE);
}
else if (containingBean != null) {
// Take default from containing bean in case of an inner bean definition.
bd.setScope(containingBean.getScope());
}
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
bd.setAutowireMode(getAutowireMode(autowire));
String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
}
String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
String candidatePattern = this.defaults.getAutowireCandidates();
if (candidatePattern != null) {
String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
}
}
else {
bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
}
if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
}
if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
if (!"".equals(initMethodName)) {
bd.setInitMethodName(initMethodName);
}
}
else {
if (this.defaults.getInitMethod() != null) {
bd.setInitMethodName(this.defaults.getInitMethod());
bd.setEnforceInitMethod(false);
}
}
if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
if (!"".equals(destroyMethodName)) {
bd.setDestroyMethodName(destroyMethodName);
}
}
else {
if (this.defaults.getDestroyMethod() != null) {
bd.setDestroyMethodName(this.defaults.getDestroyMethod());
bd.setEnforceDestroyMethod(false);
}
}
if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
}
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}
return bd;
}
解析<alias>:DefaultBeanDefinitionDocumentReader.java
protected void processAliasRegistration(Element ele) {
String name = ele.getAttribute(NAME_ATTRIBUTE); // 獲取alias element的name屬性
String alias = ele.getAttribute(ALIAS_ATTRIBUTE);// 獲取alias element的alias屬性
boolean valid = true;
if (!StringUtils.hasText(name)) {
getReaderContext().error("Name must not be empty", ele);
valid = false;
}
if (!StringUtils.hasText(alias)) {
getReaderContext().error("Alias must not be empty", ele);
valid = false;
}
if (valid) {
try {
// 將alias註冊到DefaultListableBeanFactory的aliasMap屬性中
getReaderContext().getRegistry().registerAlias(name, alias);
}
catch (Exception ex) {
getReaderContext().error("Failed to register alias '" + alias +
"' for bean with name '" + name + "'", ele, ex);
}
// 傳送alias註冊的訊息
getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
}
}
SimpleAliasRegistry.java
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
if (alias.equals(name)) {
this.aliasMap.remove(alias);
}
else {
if (!allowAliasOverriding()) {
String registeredName = this.aliasMap.get(alias);
if (registeredName != null && !registeredName.equals(name)) {
throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
}
checkForAliasCircle(name, alias);
this.aliasMap.put(alias, name); // 將alias註冊到aliasMap中
}
}
解析CustomElement
BeanDefinitionParserDelegate.java
public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele); // 獲取element的namespaceUri屬性
// 利用XmlReaderContext的DefaultNamespaceHandlerResolver namespaceHandlerResolver屬性,根據namespaceUri獲取對應的NamespaceHandler
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:component-scan>為例,說明BeanDefinitionParserDelegate是如何parseCustomElement的。
<!-- 掃描註解檔案 -->
<context:component-scan base-package="com.java" />
首先,確定NamespaceHandler:parseCustomElement根據Element的namespaceURI,確定NamespaceHandler為ContextNamespaceHandler,這樣BeanDefinitionParserDelegate將解析的工作委託給具體Namespace的NamespaceHandler:public class ContextNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
}
其次,確定BeanDefinitionParser:在<context>的Namespace下,根據具體的標籤"component-scan",確定BeanDefinitionParser為ComponentScanBeanDefinitionParser,這樣NamespaceHandler將解析的工作委託給具體BeanDefinitionParser。ContextNamespaceHandler針對其命名下的"component-scan"、"annotation-config"標籤等對應不同的BeanDefinitionParser,從而完成Element到BeanDefinition的解析工作:
NamespaceHandlerSupport.java:
// NamespaceHandler將解析工作委託給BeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 將解析工作委託給ComponentScanBeanDefinitionParser
return findParserForElement(element, parserContext).parse(element, parserContext);
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
// 獲取Element對應的localName,該例為"component-scan"
String localName = parserContext.getDelegate().getLocalName(element);
// ContextNamespaceHandler在init方法中註冊了很多BeanDefinitionParser到HashMap<String, BeanDefinitionParser> parsers,這裡從中獲取對應的
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
ComponentScanBeanDefinitionParser.java
// 解析Element為BeanDefinition,且完成註冊工作
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 獲取"base-package"屬性
String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
// 用ClassPathBeanDefinitionScanner掃描"base-package"下的BeanDefinition
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
// 註冊CompositeComponentDefinition
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
// 建立ClassPathBeanDefinitionScanner物件且進行配置
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
XmlReaderContext readerContext = parserContext.getReaderContext();
boolean useDefaultFilters = true;
if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
}
// Delegate bean definition registration to scanner class.
ClassPathBeanDefinitionScanner scanner = createScanner(readerContext, useDefaultFilters);
scanner.setResourceLoader(readerContext.getResourceLoader());
scanner.setEnvironment(parserContext.getDelegate().getEnvironment());
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) {
readerContext.error(ex.getMessage(), readerContext.extractSource(element), ex.getCause());
}
try {
parseScope(element, scanner);
}
catch (Exception ex) {
readerContext.error(ex.getMessage(), readerContext.extractSource(element), ex.getCause());
}
parseTypeFilters(element, scanner, readerContext, parserContext);
return scanner;
}
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters);
}
ClassPathBeanDefinitionScanner.java
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) {
// 查詢@Component的Class
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
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)) { // 檢測Annotation bean是否已經有同名的bean在BeanFactory註冊,如果沒有則為true
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 註冊bean到DefaultListableBeanFactory中
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
ClassPathScanningCandidateComponentProvider.java
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + "/" + this.resourcePattern;
// 獲取"classpath*:com/java/**/*.class"所有的Resource
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 {
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
if (isCandidateComponent(metadataReader)) { // 判斷是否是Component
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) { // 判斷sbd isConcrete且isIndependent
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;
}