说在前面
前期回顾
sharding-jdbc源码解析 更新完毕
spring源码解析 更新完毕
spring-mvc源码解析 更新完毕
spring-tx源码解析 更新完毕
spring-boot源码解析 更新完毕
rocketmq源码解析 更新完毕
dubbbo源码解析 更新完毕
netty源码解析 更新完毕
spring源码架构更新完毕
spring-mvc源码架构更新完毕
springboot源码架构更新中
github https://github.com/tianheframe
sharding-jdbc源码解析 更新完毕
rocketmq源码解析 更新完毕
seata 源码解析 更新完毕
dubbo 源码解析 更新完毕
netty 源码解析 更新完毕
源码解析
org.springframework.boot.liquibase.SpringPackageScanClassResolver使用Spring的资源扫描来定位类的Liquibase PackageScanClassResolver实现。此变体可以安全地与Spring Boot打包的可执行jar一起使用。
@Override protected void findAllClasses(String packageName, ClassLoader loader) { MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory( loader); try {// 扫描BeanDefinition Resource[] resources = scan(loader, packageName); for (Resource resource : resources) {// 加载类 Class> clazz = loadClass(loader, metadataReaderFactory, resource); if (clazz != null) { addFoundClass(clazz); } } } catch (IOException ex) { throw new IllegalStateException(ex); } }
扫描BeanDefinition的类,加载BeanDefinition,org.springframework.boot.liquibase.SpringPackageScanClassResolver#scan 扫描classpath下面的class类
private Resource[] scan(ClassLoader loader, String packageName) throws IOException { ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver( loader);// 加载classpath下面的class BeanDefinition String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(packageName) + "/**/*.class"; Resource[] resources = resolver.getResources(pattern); return resources; }
org.springframework.boot.context.embedded.tomcat.SkipPatternJarScanner JarScanner装饰器允许替代的默认jar模式匹配。由于Tomcat 8中引入了API更改,这个类扩展了标准JarScanner而不是实现JarScanner。
org.springframework.boot.BeanDefinitionLoader 从底层源(包括XML和JavaConfig)加载bean定义。在带注释的beandefinitionreader、XmlBeanDefinitionReader和ClassPathBeanDefinitionScanner上充当一个简单的外观。
private final AnnotatedBeanDefinitionReader annotatedReader;
基于注解的BeanDefinitionReader
private final XmlBeanDefinitionReader xmlReader;
基于xml的BeanDefinitionReader
private final ClassPathBeanDefinitionScanner scanner;
基于classpath路径BeanDefinition的scanner
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) { Assert.notNull(registry, "Registry must not be null"); Assert.notEmpty(sources, "Sources must not be empty"); this.sources = sources;// 基于注解的BeanDefinitionReader this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);// 基于xml方式的BeanDefinitionReader this.xmlReader = new XmlBeanDefinitionReader(registry); if (isGroovyPresent()) { this.groovyReader = new GroovyBeanDefinitionReader(registry); }// 基于classpath路径扫描BeanDefinition的scanner this.scanner = new ClassPathBeanDefinitionScanner(registry); this.scanner.addExcludeFilter(new ClassExcludeFilter(sources)); }
public int load() { int count = 0; for (Object source : this.sources) { count += load(source); } return count; }
加载BeanDefinition资源,org.springframework.boot.BeanDefinitionLoader#load(java.lang.Object)
private int load(Object source) { Assert.notNull(source, "Source must not be null"); if (source instanceof Class>) {// 扫描基于@Configuration配置类的BeanDefinition return load((Class>) source); }// 扫描基于配置文件的BeanDefinition if (source instanceof Resource) { return load((Resource) source); }// 加载基于包名扫描的BeanDefinition if (source instanceof Package) { return load((Package) source); } if (source instanceof CharSequence) { return load((CharSequence) source); } throw new IllegalArgumentException("Invalid source type " + source.getClass()); }
org.springframework.boot.BeanDefinitionLoader#load(java.lang.Class>) 加载基于@Configuration配置类的BeanDefinition
private int load(Class> source) { if (isGroovyPresent()) { // Any GroovyLoaders added in beans{} DSL can contribute beans here if (GroovyBeanDefinitionSource.class.isAssignableFrom(source)) { GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class); load(loader); } } if (isComponent(source)) {// 注册带有@Configuration的配置类 this.annotatedReader.register(source); return 1; } return 0; }
org.springframework.boot.BeanDefinitionLoader#load(org.springframework.core.io.Resource) 加载基于配置文件的BeanDefinition
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"); }// 加载groovy文件的BeanDefinition return this.groovyReader.loadBeanDefinitions(source); }// 加载xml文件的BeanDefinition return this.xmlReader.loadBeanDefinitions(source); }
org.springframework.boot.BeanDefinitionLoader#load(java.lang.Package) 加载基于包名扫描的BeanDefinition
private int load(Package source) { return this.scanner.scan(source.getName()); }
private boolean isComponent(Class> type) { // This has to be a bit of a guess. The only way to be sure that this type is 这是一个猜测。确定这种类型的唯一方法是 // eligible is to make a bean definition out of it and try to instantiate it.合格的方法是用它定义一个bean并尝试实例化它。// 类上是否加了@Component注解 if (AnnotationUtils.findAnnotation(type, Component.class) != null) { return true; } // Nested anonymous classes are not eligible for registration, nor are groovy 嵌套匿名类不适合注册,groovy也不适合 // closures 闭包 if (type.getName().matches(".*\\$_.*closure.*") || type.isAnonymousClass() || type.getConstructors() == null || type.getConstructors().length == 0) { return false; } return true; }
判断bean上是不是有@Component注解
说在最后
本次解析仅代表个人观点,仅供参考。
![3cb69d1be3232416722a30143907fe08.gif](https://i-blog.csdnimg.cn/blog_migrate/3e819282ab58f2b2b41f6850b5ac1c64.gif)
扫码进入技术微信群
![d0fc03a8fdff373e2fb3012fc98ea843.png](https://i-blog.csdnimg.cn/blog_migrate/f08c391b3f32dec909cab27bd7223229.jpeg)
![90536f6d31ae38674129c2c5a3820c58.png](https://i-blog.csdnimg.cn/blog_migrate/172864f049718ea7f67fd8e20537e6fb.png)
![08cff0317543d4321d2853b9bea93ccb.png](https://i-blog.csdnimg.cn/blog_migrate/e97ee2f4efc4507562693986658e95d2.png)
qq技术群