您的位置:首页 > 编程语言 > Java开发

spring boot实战(第十篇)Spring boot Bean加载源码分析

2018-01-14 00:16 971 查看



前言

前面的文章描述了Application对应Bean的创建,本篇将阐述spring boot中bean的创建过程


refresh

首先来看SpringApplication#run方法中refresh()方法

[html] view
plain copy

// Refresh the context

refresh(context);

调用的是AbstractApplicationContext中的refresh方法

[html] view
plain copy

protected void refresh(ApplicationContext applicationContext) {

Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);

((AbstractApplicationContext) applicationContext).refresh();

}

方法定义如下:

[html] view
plain copy

public void refresh() throws BeansException, IllegalStateException {

synchronized (this.startupShutdownMonitor) {

// Prepare this context for refreshing.

prepareRefresh();

// Tell the subclass to refresh the internal bean factory.

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.

prepareBeanFactory(beanFactory);

try {

// Allows post-processing of the bean factory in context subclasses.

postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.

invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.

registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.

initMessageSource();

// Initialize event multicaster for this context.

initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.

onRefresh();

// Check for listener beans and register them.

registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.

finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.

finishRefresh();

}

catch (BeansException ex) {

logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);

// Destroy already created singletons to avoid dangling resources.

destroyBeans();

// Reset 'active' flag.

cancelRefresh(ex);

// Propagate exception to caller.

throw ex;

}

}

}

该方法中涉及的过程非常多,需要一步步来分析

获取BeanFactory

[html] view
plain copy

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

通过前面的文章应该知道对应的BeanFactory为DefaultListableBeanFactory

直奔主题来看如下方法

[html] view
plain copy

invokeBeanFactoryPostProcessors(beanFactory);

[html] view
plain copy

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

}

首先来看getBeanFactoryPostProcessors(),其对应值为:ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor、PropertySourceOrderingPostProcessor

ConfigurationWarningsApplicationContextInitializer是在ConfigurationWarningsApplicationContextInitializer中执行

[html] view
plain copy

public void initialize(ConfigurableApplicationContext context) {

context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(

getChecks()));

}

添加

PropertySourceOrderingPostProcessor是在ConfigFileApplicationListener执行

[html] view
plain copy

protected void addPostProcessors(ConfigurableApplicationContext context) {

context.addBeanFactoryPostProcessor(new PropertySourceOrderingPostProcessor(

context));

}

添加

来看invokeBeanFactoryPostProcessors方法

[html] view
plain copy

public static void invokeBeanFactoryPostProcessors(

ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

// Invoke BeanDefinitionRegistryPostProcessors first, if any.

Set<String> processedBeans = new HashSet<String>();

if (beanFactory instanceof BeanDefinitionRegistry) {

...//处理后处理器

String[] postProcessorNames =

beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.

List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();

for (String ppName : postProcessorNames) {

if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {

priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));

processedBeans.add(ppName);

}

}

OrderComparator.sort(priorityOrderedPostProcessors);

registryPostProcessors.addAll(priorityOrderedPostProcessors);

invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);

// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.

postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();

for (String ppName : postProcessorNames) {

if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {

orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));

processedBeans.add(ppName);

}

}

OrderComparator.sort(orderedPostProcessors);

registryPostProcessors.addAll(orderedPostProcessors);

invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.

boolean reiterate = true;

while (reiterate) {

reiterate = false;

postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

for (String ppName : postProcessorNames) {

if (!processedBeans.contains(ppName)) {

BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);

registryPostProcessors.add(pp);

processedBeans.add(ppName);

pp.postProcessBeanDefinitionRegistry(registry);

reiterate = true;

}

}

}

// Now, invoke the postProcessBeanFactory callback of all processors handled so far 执行后处理器

invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);

invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

}

[html] view
plain copy

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

按照bean的类型获取类型为BeanDefinitionRegistryPostProcessor的bean,这里获取到的bean名称为:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor;对应的Class为ConfigurationClassPostProcessor
在前面文章中创建上下文的时候beanfactory创建了该bean。
经过排序后执行如下方法

[html] view
plain copy

invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);

[html] view
plain copy

private static void invokeBeanDefinitionRegistryPostProcessors(

Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {

postProcessor.postProcessBeanDefinitionRegistry(registry);

}

}

实际调用ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry

[html] view
plain copy

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {

...//注册若干bean

processConfigBeanDefinitions(registry);

}

processConfigBeanDefinitions(registry)如下:

[html] view
plain copy

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {

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

String[] candidateNames = registry.getBeanDefinitionNames();

for (String beanName : candidateNames) {

BeanDefinition beanDef = registry.getBeanDefinition(beanName);

if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||

ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {

if (logger.isDebugEnabled()) {

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

}

}

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

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

}

}

// Return immediately if no @Configuration classes were found

if (configCandidates.isEmpty()) {

return;

}

// Detect any custom bean name generation strategy supplied through the enclosing application context

SingletonBeanRegistry singletonRegistry = null;

if (registry instanceof SingletonBeanRegistry) {

singletonRegistry = (SingletonBeanRegistry) registry;

if (!this.localBeanNameGeneratorSet && singletonRegistry.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {

BeanNameGenerator generator = (BeanNameGenerator) singletonRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);

this.componentScanBeanNameGenerator = generator;

this.importBeanNameGenerator = generator;

}

}

// Parse each @Configuration class

ConfigurationClassParser parser = new ConfigurationClassParser(

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

this.resourceLoader, this.componentScanBeanNameGenerator, registry);

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

do {

parser.parse(configCandidates);

parser.validate();

Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());

configClasses.removeAll(alreadyParsed);

// Read the model and create bean definitions based on its content

if (this.reader == null) {

this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor,

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

this.importBeanNameGenerator, parser.getImportRegistry());

}

this.reader.loadBeanDefinitions(configClasses);

alreadyParsed.addAll(configClasses);

configCandidates.clear();

if (registry.getBeanDefinitionCount() > candidateNames.length) {

String[] newCandidateNames = registry.getBeanDefinitionNames();

Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));

Set<String> alreadyParsedClasses = new HashSet<String>();

for (ConfigurationClass configurationClass : alreadyParsed) {

alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());

}

for (String candidateName : newCandidateNames) {

if (!oldCandidateNames.contains(candidateName)) {

BeanDefinition beanDef = registry.getBeanDefinition(candidateName);

if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory) &&

!alreadyParsedClasses.contains(beanDef.getBeanClassName())) {

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

}

}

}

candidateNames = newCandidateNames;

}

}

while (!configCandidates.isEmpty());

// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes

if (singletonRegistry != null) {

if (!singletonRegistry.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {

singletonRegistry.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());

}

}

if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {

((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();

}

}

又是一段很长的代码

[html] view
plain copy

String[] candidateNames = registry.getBeanDefinitionNames();

获取已经注册的bean名称,其信息为:

这里看到上一篇中创建的Application对应bean

[html] view
plain copy

for (String beanName : candidateNames) {

BeanDefinition beanDef = registry.getBeanDefinition(beanName);

if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||

ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {

if (logger.isDebugEnabled()) {

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

}

}

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

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

}

}

判断对应bean是否为配置文件bean(包含Configuration注解),经过筛选只有Application对应bean满足条件

[html] view
plain copy

ConfigurationClassParser parser = new ConfigurationClassParser(

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

this.resourceLoader, this.componentScanBeanNameGenerator, registry);

该代码构造了Configuration类解析器

执行

[html] view
plain copy

parser.parse(configCandidates);

[html] view
plain copy

public void parse(Set<BeanDefinitionHolder> configCandidates) {

this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();

for (BeanDefinitionHolder holder : configCandidates) {

BeanDefinition bd = holder.getBeanDefinition();

try {

if (bd instanceof AnnotatedBeanDefinition) { //执行该部分代码

parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());

}

else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {

parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());

}

else {

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

}

}

catch (BeanDefinitionStoreException ex) {

throw ex;

}

catch (Exception ex) {

throw new BeanDefinitionStoreException(

"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);

}

}

processDeferredImportSelectors();

}

调用

[html] view
plain copy

parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());

最终调用

[html] view
plain copy

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {

if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {

return;

}

ConfigurationClass existingClass = this.configurationClasses.get(configClass);

if (existingClass != null) {

if (configClass.isImported()) {

if (existingClass.isImported()) {

existingClass.mergeImportedBy(configClass);

}

// Otherwise ignore new imported config class; existing non-imported class overrides it.

return;

}

else {

// Explicit bean definition found, probably replacing an import.

// Let's remove the old one and go with the new one.

this.configurationClasses.remove(configClass);

for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext(); ) {

if (configClass.equals(it.next())) {

it.remove();

}

}

}

}

// Recursively process the configuration class and its superclass hierarchy.

SourceClass sourceClass = asSourceClass(configClass);

do {

sourceClass = doProcessConfigurationClass(configClass, sourceClass);

}

while (sourceClass != null);

this.configurationClasses.put(configClass, configClass);

}

首先判断该bean是否被跳过(该部分代码上一篇已说明),然后对Class进行包装,调用sourceClass = doProcessConfigurationClass(configClass,sourceClass)处理Application类


解析Configuration注解

[html] view
plain copy

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {

// Recursively process any member (nested) classes first

processMemberClasses(configClass, sourceClass);

// Process any @PropertySource annotations

for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(

sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) {

if (this.environment instanceof ConfigurableEnvironment) {

processPropertySource(propertySource);

}

else {

logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +

"]. Reason: Environment must implement ConfigurableEnvironment");

}

}

// Process any @ComponentScan annotations

AnnotationAttributes componentScan = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ComponentScan.class);

if (componentScan != null && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {

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

Set<BeanDefinitionHolder> scannedBeanDefinitions =

this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

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

for (BeanDefinitionHolder holder : scannedBeanDefinitions) {

if (ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(), this.metadataReaderFactory)) {

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

}

}

}

// Process any @Import annotations

processImports(configClass, sourceClass, getImports(sourceClass), true);

// Process any @ImportResource annotations

if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {

AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);

String[] resources = importResource.getStringArray("value");

Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");

for (String resource : resources) {

String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);

configClass.addImportedResource(resolvedResource, readerClass);

}

}

// Process individual @Bean methods

Set<MethodMetadata> beanMethods = sourceClass.getMetadata().getAnnotatedMethods(Bean.class.getName());

for (MethodMetadata methodMetadata : beanMethods) {

configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));

}

// Process superclass, if any

if (sourceClass.getMetadata().hasSuperClass()) {

String superclass = sourceClass.getMetadata().getSuperClassName();

if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {

this.knownSuperclasses.put(superclass, configClass);

// Superclass found, return its annotation metadata and recurse

return sourceClass.getSuperClass();

}

}

// No superclass -> processing is complete

return null;

}

到这里就看到了如何去解析Application类

[html] view
plain copy

processMemberClasses(configClass, sourceClass);

处理其中内部类,解析内部类的过程和外部类相似,因此继续看下面的代码


处理PropertySource注解

[html] view
plain copy

// Process any @PropertySource annotations

for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(

sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) {

if (this.environment instanceof ConfigurableEnvironment) {

processPropertySource(propertySource);

}

else {

logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +

"]. Reason: Environment must implement ConfigurableEnvironment");

}

}<pre name="code" class="html">

[html] view
plain copy



其核心操作:

[html] view
plain copy

private void processPropertySource(AnnotationAttributes propertySource) throws IOException {

String name = propertySource.getString("name");

String[] locations = propertySource.getStringArray("value");

boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");

Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");

for (String location : locations) {

try {

String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);

Resource resource = this.resourceLoader.getResource(resolvedLocation);

ResourcePropertySource rps = (StringUtils.hasText(name) ?

new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource));

addPropertySource(rps);

}

catch (IllegalArgumentException ex) {

// from resolveRequiredPlaceholders

if (!ignoreResourceNotFound) {

throw ex;

}

}

catch (FileNotFoundException ex) {

// from ResourcePropertySource constructor

if (!ignoreResourceNotFound) {

throw ex;

}

}

}

}

通过注解中的信息获取资源信息,然后添加到MutablePropertySourcespropertySources = ((ConfigurableEnvironment)this.environment).getPropertySources()中,该内容前面已有讲述


解析ComponentScan注解

[html] view
plain copy

// Process any @ComponentScan annotations

AnnotationAttributes componentScan = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ComponentScan.class);

if (componentScan != null && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {

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

Set<BeanDefinitionHolder> scannedBeanDefinitions =

this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

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

for (BeanDefinitionHolder holder : scannedBeanDefinitions) {

if (ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(), this.metadataReaderFactory)) {

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

}

}

}

ComponentScan注解的作用大家都明白,扫描执行路径下bean信息,那么具体是如何实现的?需要跟进去看代码,调用

[html] view
plain copy

Set<BeanDefinitionHolder> scannedBeanDefinitions =

this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

[html] view
plain copy

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

...//通过注解中的信息设置扫描器的参数信息

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

}

代码中忽略了扫描器对应的参数信息,直接看doScan方法

[html] view
plain copy

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) {

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)) {

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);

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

beanDefinitions.add(definitionHolder);

registerBeanDefinition(definitionHolder, this.registry);

}

}

}

return beanDefinitions;

}

遍历basePackages信息,

[html] view
plain copy

Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

查询类路径下申明的组件信息,

[html] view
plain copy

public Set<BeanDefinition> findCandidateComponents(String basePackage) {

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

try {

String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +

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

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)) {

ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);

sbd.setResource(resource);

sbd.setSource(resource);

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;

}



[html] view
plain copy

Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);

[html] view
plain copy

public Resource[] getResources(String locationPattern) throws IOException {

Assert.notNull(locationPattern, "Location pattern must not be null");

if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {

// a class path resource (multiple resources for same name possible)

if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {

// a class path resource pattern

return findPathMatchingResources(locationPattern);

}

else {

// all class path resources with the given name

return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));

}

}

else {

// Only look for a pattern after a prefix here

// (to not get fooled by a pattern symbol in a strange prefix).

int prefixEnd = locationPattern.indexOf(":") + 1;

if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {

// a file pattern

return findPathMatchingResources(locationPattern);

}

else {

// a single resource with the given name

return new Resource[] {getResourceLoader().getResource(locationPattern)};

}

}

}

解析路径信息,这里spring有自己的一套继续规则,通过findPathMatchingResources()检索到指定类路径下所有的*.class文件,然后调用findAllClassPathResources解析Class文件

[html] view
plain copy

protected Resource[] findAllClassPathResources(String location) throws IOException {

String path = location;

if (path.startsWith("/")) {

path = path.substring(1);

}

Set<Resource> result = doFindAllClassPathResources(path);

return result.toArray(new Resource[result.size()]);

}

[html] view
plain copy

protected Set<Resource> doFindAllClassPathResources(String path) throws IOException {

Set<Resource> result = new LinkedHashSet<Resource>(16);

ClassLoader cl = getClassLoader();

Enumeration<URL> resourceUrls = (cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path));

while (resourceUrls.hasMoreElements()) {

URL url = resourceUrls.nextElement();

result.add(convertClassLoaderURL(url));

}

if ("".equals(path)) {

// The above result is likely to be incomplete, i.e. only containing file system references.

// We need to have pointers to each of the jar files on the classpath as well...

addAllClassLoaderJarRoots(cl, result);

}

return result;

}

通过上面的代码可以发现,在获取到path路径以后spring采用类加载器获取指定Class文件对应的资源信息

获取完资源信息后调用

[html] view
plain copy

MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);

解析资源信息对应的元数据

[html] view
plain copy

if (isCandidateComponent(metadataReader)) {

ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);

sbd.setResource(resource);

sbd.setSource(resource);

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);

}

}

如果存在Componment注解修饰的Class文件则加入到BeanDefinition集合中返回。

回到调用扫描bean处

[html] view
plain copy

for (BeanDefinitionHolder holder : scannedBeanDefinitions) {

if (ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(), this.metadataReaderFactory)) {

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

}

}

遍历扫描到的bean信息,如果为配置bean,则执行parse方法,该方法调用processConfigurationClass,形成一个递归的操作。


解析Import注解

[html] view
plain copy

<span style="font-family:Arial, Helvetica, sans-serif;"> </span><span style="font-family: Arial, Helvetica, sans-serif;">processImports(</span><span class="s1" style="font-family: Arial, Helvetica, sans-serif;">configClass</span><span style="font-family: Arial, Helvetica, sans-serif;">, </span><span class="s1" style="font-family: Arial, Helvetica, sans-serif;">sourceClass</span><span style="font-family: Arial, Helvetica, sans-serif;">, getImports(</span><span class="s1" style="font-family: Arial, Helvetica, sans-serif;">sourceClass</span><span style="font-family: Arial, Helvetica, sans-serif;">), </span><span class="s2" style="font-family: Arial, Helvetica, sans-serif;">true</span><span style="font-family: Arial, Helvetica, sans-serif;">);</span>

处理import注解,该注解在spring boot中使用非常频繁

[html] view
plain copy

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,

Collection<SourceClass> importCandidates, boolean checkForCircularImports) throws IOException {

...

this.importStack.push(configClass);

try {

for (SourceClass candidate : importCandidates) {

if (candidate.isAssignable(ImportSelector.class)) {

// Candidate class is an ImportSelector -> delegate to it to determine imports

Class<?> candidateClass = candidate.loadClass();

ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);

invokeAwareMethods(selector);

if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {

this.deferredImportSelectors.add(

new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));

}

else {

String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());

Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);

processImports(configClass, currentSourceClass, importSourceClasses, false);

}

}

else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {

// Candidate class is an ImportBeanDefinitionRegistrar ->

// delegate to it to register additional bean definitions

Class<?> candidateClass = candidate.loadClass();

ImportBeanDefinitionRegistrar registrar =

BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);

invokeAwareMethods(registrar);

configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());

}

else {

// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->

// process it as an @Configuration class

this.importStack.registerImport(

currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());

processConfigurationClass(candidate.asConfigClass(configClass));

}

}

}

catch (BeanDefinitionStoreException ex) {

throw ex;

}

catch (Exception ex) {

throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +

configClass.getMetadata().getClassName() + "]", ex);

}

finally {

this.importStack.pop();

}

}

}

如果Import注解中Class为ImportSelector子类,通过invokeAwareMethods(selector)设置aware值,如果类型为DeferredImportSelector则添加到deferredImportSelectors集合中,待前面的parser.parse(configCandidates)

方法中processDeferredImportSelectors()处理;如果不是,则执行selectImports方法,将获取到的结果递归调用processImports,解析selectImports得到的结果
如果Import注解中Class为ImportBeanDefinitionRegistrar子类,则添加到importBeanDefinitionRegistrars中,注意该部分的数据在执行完parser.parse(configCandidates)后调用this.reader.loadBeanDefinitions(configClasses)解析
否则执行配置信息的解析操作。


解析ImportResource注解

[html] view
plain copy

// Process any @ImportResource annotations

if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {

AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);

String[] resources = importResource.getStringArray("value");

Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");

for (String resource : resources) {

String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);

configClass.addImportedResource(resolvedResource, readerClass);

}

}


解析Bean注解

[html] view
plain copy

Set<MethodMetadata> beanMethods = sourceClass.getMetadata().getAnnotatedMethods(Bean.class.getName());

for (MethodMetadata methodMetadata : beanMethods) {

configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));

}

上面这两个注解相对来讲要简单一些,至此bean的解析完成,这里面涉及到多重递归,首先理清楚一条线才能把代码看明白。

转载请注明
http://blog.csdn.net/liaokailin/article/details/49107209
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: