赞
踩
关于springboot系列详细分析,可以参考这里。
在这篇文章中分析了springboot启动的详细过程,其中涉及到了bean定义的加载,但是并没有详细讲解这个过程,本文一起来看下。
方法org.springframework.boot.SpringApplication#run(java.lang.String...)
,源码如下:
org.springframework.boot.SpringApplication#run(java.lang.String...)
public ConfigurableApplicationContext run(String... args) {
...snip...
try {
...snip...
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
...snip...
}
catch (Throwable ex) {
...snip...
}
...snip...
return context;
}
继续:
org.springframework.boot.SpringApplication#prepareContext private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { ...snip... // 启动类的class,我这里是 // ["class com.example.springbootintegarationspringmvc.SpringbootIntegrationSpringmvcApplication"] // 该处源码如下: /* org.springframework.boot.SpringApplication#getAllSources public Set<Object> getAllSources() { Set<Object> allSources = new LinkedHashSet<>(); if (!CollectionUtils.isEmpty(this.primarySources)) { allSources.addAll(this.primarySources); } if (!CollectionUtils.isEmpty(this.sources)) { allSources.addAll(this.sources); } return Collections.unmodifiableSet(allSources); } */ Set<Object> sources = getAllSources(); // <202106281455> load(context, sources.toArray(new Object[0])); ...snip... }
<202106281455>
处源码如下:
org.springframework.boot.SpringApplication#load protected void load(ApplicationContext context, Object[] sources) { if (logger.isDebugEnabled()) { logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources)); } // <202106281506> // 创建bean定义加载器 BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources); // <202106281543> if (this.beanNameGenerator != null) { loader.setBeanNameGenerator(this.beanNameGenerator); } // <202106281549> if (this.resourceLoader != null) { loader.setResourceLoader(this.resourceLoader); } // <202106281551> if (this.environment != null) { loader.setEnvironment(this.environment); } // <202106281553> loader.load(); }
<202106281506>
处是创建bean定义加载器,具体参考1.1:createBeanDefinitionLoader
。<202106281543>
处是设置bean名称生成器,源码如下:
org.springframework.boot.BeanDefinitionLoader#setBeanNameGenerator
// 设置底层读取器,扫描器使用的bean名称生成器
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
this.annotatedReader.setBeanNameGenerator(beanNameGenerator);
this.xmlReader.setBeanNameGenerator(beanNameGenerator);
this.scanner.setBeanNameGenerator(beanNameGenerator);
}
<202106281549>
处是设置用于加载资源的资源加载器,源码如下:
org.springframework.boot.BeanDefinitionLoader#setResourceLoader
public void setResourceLoader(ResourceLoader resourceLoader) {
// 赋值到全局变量
this.resourceLoader = resourceLoader;
// 设置资源加载器到读取器
this.xmlReader.setResourceLoader(resourceLoader);
// 设置资源加载器到扫描器
this.scanner.setResourceLoader(resourceLoader);
}
<202106281551>
处源码如下:
org.springframework.boot.BeanDefinitionLoader#setEnvironment
// 设置底层读取器和扫描器使用的环境对象
public void setEnvironment(ConfigurableEnvironment environment) {
this.annotatedReader.setEnvironment(environment);
this.xmlReader.setEnvironment(environment);
this.scanner.setEnvironment(environment);
}
<202106281553>
处是执行具体的加载,具体参考2:load
。
源码如下:
org.springframework.boot.SpringApplication#createBeanDefinitionLoader
// 创建BeanDefintionLoader的工厂方法
protected BeanDefinitionLoader createBeanDefinitionLoader(BeanDefinitionRegistry registry, Object[] sources) {
// <202106281509>
return new BeanDefinitionLoader(registry, sources);
}
<202106281509>
处源码如下:
org.springframework.boot.BeanDefinitionLoader#BeanDefinitionLoader // registry:注册bean定义的bean定义注册器 // sources:需要加载为bean定义的资源 BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) { Assert.notNull(registry, "Registry must not be null"); Assert.notEmpty(sources, "Sources must not be empty"); // 赋值到全局变量 this.sources = sources; // 基于注解的bean定义读取器 this.annotatedReader = new AnnotatedBeanDefinitionReader(registry); // 基于xml的bean定义读取器 this.xmlReader = new XmlBeanDefinitionReader(registry); // 是否使用groovy,源码如下: /* org.springframework.boot.BeanDefinitionLoader#isGroovyPresent private boolean isGroovyPresent() { return ClassUtils.isPresent("groovy.lang.MetaClass", null); } */ if (isGroovyPresent()) { this.groovyReader = new GroovyBeanDefinitionReader(registry); } // bean定义扫描器 this.scanner = new ClassPathBeanDefinitionScanner(registry); // 设置排除,防止重复扫描 this.scanner.addExcludeFilter(new ClassExcludeFilter(sources)); }
源码如下:
org.springframework.boot.BeanDefinitionLoader#load()
public int load() {
int count = 0;
for (Object source : this.sources) {
// <202106281603>
count += load(source);
}
return count;
}
<202106281603>
处源码如下:
org.springframework.boot.BeanDefinitionLoader#load(java.lang.Object) private int load(Object source) { Assert.notNull(source, "Source must not be null"); // <202106281606> if (source instanceof Class<?>) { return load((Class<?>) source); } // <202106281607> if (source instanceof Resource) { return load((Resource) source); } // <202106281608> if (source instanceof Package) { return load((Package) source); } // <202106281609> if (source instanceof CharSequence) { return load((CharSequence) source); } throw new IllegalArgumentException("Invalid source type " + source.getClass()); }
<202106281606>
处参考2.1:加载class资源为bean定义
。<202106281607>
处参考2.2:加载Resource为bean定义
。<202106281608>
处如果是包路径的话,执行的加载,具体参考2.3:加载Package为bean定义
,<202106281609>
处如果是字符串路径,具体参考加载CharSequence为bean定义
。
源码如下:
org.springframework.boot.BeanDefinitionLoader#load(java.lang.Class<?>)
private int load(Class<?> source) {
// 忽略
if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
load(loader);
}
// <202106281646>
if (isComponent(source)) {
// 执行注册,spring的内容了,此处不深究
this.annotatedReader.register(source);
return 1;
}
return 0;
}
<202106281646>
处源码如下:
org.springframework.boot.BeanDefinitionLoader#isComponent
private boolean isComponent(Class<?> type) {
// 如果是有@Component注解(如@Configuration注解也是为true,因为组合了@Component注解)
if (AnnotationUtils.findAnnotation(type, Component.class) != null) {
return true;
}
// 忽略
if (type.getName().matches(".*\\$_.*closure.*") || type.isAnonymousClass() || type.getConstructors() == null
|| type.getConstructors().length == 0) {
return false;
}
// 默认返回true
return true;
}
源码如下:
org.springframework.boot.BeanDefinitionLoader#load(org.springframework.core.io.Resource)
private int load(Resource source) {
// 忽略
if(source.getFilename().endsWith(".groovy")) {
if (this.groovyReader == null) {
throw new BeanDefinitionStoreException("Cannot load Groovy beans without Groovy on classpath");
}
return this.groovyReader.loadBeanDefinitions(source);
}
// 执行bean定义的加载,此处是spring的内容了,不深究
return this.xmlReader.loadBeanDefinitions(source);
}
源码如下:
org.springframework.boot.BeanDefinitionLoader#load(java.lang.Package)
private int load(Package source) {
// 执行bean定义的加载,此处是spring的内容了,不深究
return this.scanner.scan(source.getName());
}
源码如下:
// 按照Class(source是类全限定名) > Resource(source是xml配置文件路径) > Package的情况依次尝试加载(source是包路径) private int load(CharSequence source) { // 处理可能存在的占位符 String resolvedSource = this.xmlReader.getEnvironment().resolvePlaceholders(source.toString()); try { // 尝试class加载 return load(ClassUtils.forName(resolvedSource, null)); } catch (IllegalArgumentException | ClassNotFoundException ex) { // 发生异常,这里什么也不做,继续后续 } // 尝试Resource假记载 Resource[] resources = findResources(resolvedSource); int loadCount = 0; boolean atLeastOneResourceExists = false; for (Resource resource : resources) { if (isLoadCandidate(resource)) { atLeastOneResourceExists = true; loadCount += load(resource); } } if (atLeastOneResourceExists) { return loadCount; } // 尝试Package加载 Package packageResource = findPackage(resolvedSource); if (packageResource != null) { return load(packageResource); } throw new IllegalArgumentException("Invalid source '" + resolvedSource + "'"); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。