Общая документация:Каталог статей
Github : github.com/black-ant
Введение
Вторая статья IOC все еще выбирает мягкую хурму, В этой статье говорится о методе загрузки ресурсов и документов, который также относительно прост.
Система сканирующей части включает несколько частей Resource , Document , Annotation , здесь упомянуты только первые две
2. Статьи системы ресурсов
Ресурс - это основа всего. Все внешние объекты можно рассматривать как Ресурс. По этой причине Spring предоставляет множество классов реализации Ресурса:
Common Resource в основном используется для следующих функций:
// 当用不同的 ResourceLoader 加载资源的时候 , 会根据资源类型的不同 , 选择生成不同的 Resource
C- ByteArrayResource : 给定字节数组的资源实现 , 用于从任何给定的字节数组加载内容,而不必求助于单一使用的InputStreamResource
C- ClassPathResource : 类路径资源的资源实现 , 使用给定的ClassLoader或给定的Class来加载资源
C- ContextResource : 用于从封闭的“上下文”加载资源的扩展接口
C- DescriptiveResource : 保存资源描述但不指向实际可读资源的简单资源实现
C- EncodedResource : 将资源描述符与用于从资源中读取的特定编码或字符集组合在一起
C- FileSystemResource : 资源实现处理一个文件系统目标
C- FileUrlResource : 它假定文件解析,达到实现WritableResource接口的程度
C- HttpResource : 将资源写入HTTP响应的扩展接口
C- ImportResource : 指示一个或多个包含要导入的bean定义的资源
C- InputStreamResource : 给定InputStream的资源实现 , 只在没有其他特定资源实现适用的情况下使用
C- ServletContextResource : ServletContext资源的资源实现,解释web应用程序根目录中的相对路径
C- VfsResource : 基于JBoss VFS的资源实现
C- WritableResource : 支持向资源写入的资源的扩展接口。提供一个输出流访问器
Функция системы ресурсов:
// 统一资源的核心类是 : Resource , 为 Spring 框架所有资源的抽象和访问接口
I- Resource
E- InputStreamSource
C- AbstractResource
I- Resource
> 以上是统一资源管理中核心的三个类 ,他们的继承关系如上
: Spring 中所有的资源都可以用 Resource 表示
: AbstractResource 继承自 Resource ,并且对其做了实现
> Resource 中有很多常见的功能
exists / isReadable / isOpen / isFile / getURL / getFile / readableChannel
contentLength / lastModified / createRelative / getFileName / getDescription
> AbstractResource 有以下通用的实现
- FileSystemResource : 对 java.io.File 类型资源的封装,只要是跟 File 打交道的,基本上与 FileSystemResource 也可以打交道
- 支持文件和 URL 的形式,实现 WritableResource 接口,从 Spring Framework 5.0 开始,FileSystemResource 使用 NIO2 API进行读/写交互
- ByteArrayResource : 对字节数组提供的数据的封装。
- URIResource : 对 java.net.URL类型资源的封装。内部委派 URL 进行具体的资源操作。
- ClassPathResource : class path 类型资源的实现。使用给定的 ClassLoader 或者给定的 Class 来加载资源。
- InputStreamResource : 将给定的 InputStream 作为一种资源的 Resource 的实现类。
C- AbstractResource
- exists() : 判断文件是否存在
Реализация Ресурсного интерфейса
C- AbstractResource
TODO
Ресурс будет загружаться через ResourceLoader, важный ResourceLoader содержит следующую структуру:
Следует отметить, что: ApplicationContext — это в основном класс реализации ResourceLoader, поэтому они обычно имеют функцию ResourceLoader.
Система загрузки ResourceLoader
> Spring 通过 ResourceLoader 来进行 资源的加载
C11- ResourceLoader : 资源的加载
M- getResource() : 根据所提供资源的路径 location 返回 Resource 实例
- 支持 URL位置资源 / ClassPath位置资源 / 相对路径资源
M- getClassLoader() : 返回 ClassLoader 实例
MC- ResourceLoader(ClassLoader)
- Thread.currentThread().getContextClassLoader()
- ClassUtils.getDefaultClassLoader()
- setClassLoader()
: interface ResourcePatternResolver extends ResourceLoader
C18- DefaultResourceLoader
MC- DefaultResourceLoader
- ClassUtils.getDefaultClassLoader();
MC- DefaultResourceLoader(@Nullable ClassLoader classLoader)
M- addProtocolResolver(ProtocolResolver) : 自定义的 Resolver 加入 Spring 体系
M- getResource(String location)
- 首先,通过 ProtocolResolver 来加载资源 , 成功返回 Resource
- 其次,以 / 开头,调用 #getResourceByPath() 方法, 返回 ClassPathContextResource 类型的资源
- 再次,以 classpath: 开头,返回 ClassPathResource 类型的资源
- 通过#getClassLoader() 获取当前的 ClassLoader
- 然后,根据是否为文件 URL ,是则返回 FileUrlResource 类型的资源,否则返回 UrlResource 类型的资源
- 最后,返回 ClassPathContextResource 类型的资源
// resourceLoader.getResource("D:/Users/chenming673/Documents/spark.txt");
C- ResourcePatternResolver : ResourceLoader 的默认实现
M- setClassLoader / getClassLoader
> FileSystemResourceLoader
内部类 : FileSystemContextResource extends FileSystemResource
C- ProtocolResolver : 用户自定义协议资源解决策略
?- 作为 DefaultResourceLoader 的 SPI:它允许用户自定义资源加载协议,而不需要继承 ResourceLoader 的子类
?- 现 ProtocolResolver 接口也可以实现自定义的 ResourceLoader
M- resolve(String , ResourceLoader )
Основные классы, участвующие в процессе загрузки ресурсов
// XML 流程 Resource 加载 , 我们还是从 BeanDefinitionReader 开始看起
C160- AbstractBeanDefinitionReader
M- loadBeanDefinitions(location, null)
M- loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources)
- getResourceLoader 获取一个 ResourceLoader
- ResourceLoader 通过 location 获取 Resource[] ->
- 讲获取的 Resource 加入 actualResources , 用于后方处理
C16- ResourcePatternResolver
C51- GenericApplicationContext
M51_033- getResources(String locationPattern)
C17- PathMatchingResourcePatternResolver
M17_02- getResources(String locationPattern)
- classpath*: 开头 , 则分别调用 findPathMatchingResources (-> ) / findAllClassPathResources
- getResourceLoader() 调用获取 Resource -> M18_05
M17_03- findPathMatchingResources
- 获取路径 ,递归获取包路径
- 通过包 URLResource 调用 doFindPathMatchingFileResources 获取类
M17_04- findAllClassPathResources
- 调用 doFindAllClassPathResources 获取 classResource
M17_05- doFindAllClassPathResources
- 获取一个 ClassLoader , 通过 ClassLoader 获取 resource url
- 通过 convertClassLoaderURL 对 URL 列表转换为 UrlResource
?- 这里其实还是包路径 -> PS:M17_05_01
// PS:M17_05_01
file:/D:/java/workspace/git/case/case%20Origin%20Source/case%20SpringBootIOC/target/classes/com/gang/study/source/springboot/demo/
C18- DefaultResourceLoader
M18_05- getResource(String location)
- 如果存在 ProtocolResolvers 集合, 则循环集合 , 试图用 ProtocolResolver 处理返回
- 如果是 / 开头 , 则生成一个 ClassPathContextResource
- 如果是 classpath 打头 ,new 创建出一个 ClassPathResource , 并且为其配置一个 ClassLoader
?- 所以 , 这里 bean.xml 是被映射为 ClassPathResource
- 如果是 URL 类型 , 构建为一个 FileUrlResource
// M17_03 伪代码
// locationPattern -- classpath*:com/gang/study/source/springboot/demo/**/*.class
protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
// classpath*:com/gang/study/source/springboot/demo/
String rootDirPath = determineRootDir(locationPattern);
// **/*.class
String subPattern = locationPattern.substring(rootDirPath.length());
// 扫描路径 , 将路径下资源转换为Resource数组
Resource[] rootDirResources = getResources(rootDirPath);
Set<Resource> result = new LinkedHashSet<>(16);
for (Resource rootDirResource : rootDirResources) {
rootDirResource = resolveRootDirResource(rootDirResource);
URL rootDirUrl = rootDirResource.getURL();
if (equinoxResolveMethod != null && rootDirUrl.getProtocol().startsWith("bundle")) {
URL resolvedUrl = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirUrl);
if (resolvedUrl != null) {
rootDirUrl = resolvedUrl;
}
rootDirResource = new UrlResource(rootDirUrl);
}
if (rootDirUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
// VFS 的加载方式
result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, getPathMatcher()));
}else if (ResourceUtils.isJarURL(rootDirUrl) || isJarResource(rootDirResource)) {
// JAR 包路径的加载
result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirUrl, subPattern));
}else {
// 加载类
result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
}
}
return result.toArray(new Resource[0]);
}
Несколько сценариев загрузки Ресурса, которые обычно можно увидеть по локации
Тип 1: classpath*:com/gang/study/source/springboot/demo/**/*.class
//这种路径 , 其源头为 ComponentScanAnnotationParser 开始 , 更早的源头是 Configuration 的相关扫描逻辑
C153- ComponentScanAnnotationParser
M153_01- parse : 由该方法扫描处理 ComponentScan -> M155_03
C155- ClassPathBeanDefinitionScanner
M155_03- doScan(String... basePackages) -> M201_03
C201- ClassPathScanningCandidateComponentProvider
M201_03- scanCandidateComponents(String basePackage)
- 构建一个地址 -> PS:201_03_01
- 调用 ResourcePatternResolver(AnnotationConfigServletWebServerApplicationContext) 获取 Resouce
- 最终调用 M17_02
C17- PathMatchingResourcePatternResolver
M17_02- getResources(String locationPattern)
- Class 前缀 , 最终调用 M17_03
M17_03- findPathMatchingResources
M17_04- findAllClassPathResources
// M201_03 伪代码
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
//...................
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
// PS:201_03_01
// com.gang.study.source.springboot.demo 转变为
// classpath*:com/gang/study/source/springboot/demo/**/*.class
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
//...................
}
Загрузка пре-ресурсов:
Загрузка Ресурсных ресурсов:
- M17_02 : getResources
- M17_03 : findPathMatchingResources
- M17_04 : findAllClassPathResources
- M17_05 : doFindAllClassPathResources
Основная логика такова:
- Если путь должен быть сопоставлен: findPathMatchingResources
- Среди них, сопоставив, вызовите findAllClassPathResources, чтобы получить реальный путь
- По реальному пути вызовите doFindAllClassPathResources, чтобы получить конкретный ресурс класса
Тип 2: путь к классам*: загрузка ресурса messages.properties
Загрузка пре-ресурсов:
// 这种情况的加载主要来源于 Configuration , 例如 MessageSourceAutoConfiguration
// 此处对 message 资源进行加载 , 调用 ResourceBundleCondition 进行资源加载
C202- ResourceBundleCondition
M202_01- getMatchOutcomeForBasename
M202_02- getResources
- 通过一个 classLoader 构建了一个 PathMatchingResourcePatternResolver
- 调用 getResources 返回相关的 resource 资源
?- 这里因为需要指定的资源 , 所以方式是定下了的
// M202_02 伪代码
private Resource[] getResources(ClassLoader classLoader, String name) {
String target = name.replace('.', '/');
return new PathMatchingResourcePatternResolver(classLoader).getResources("classpath*:" + target + ".properties");
}
// 同样的 , 调用了 PathMatchingResourcePatternResolver
// 此处无需匹配 , 直接 调用 findAllClassPathResources
C17- PathMatchingResourcePatternResolver
M17_02- getResources(String locationPattern)
- 无需匹配 , 直接 调用 findAllClassPathResources -> M17_04
M17_04- findAllClassPathResources
Тип 3: ресурс типа xml
Возьмем classpath:spring-common.xml в качестве примера.
// 起源 :
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
?- 即 ImportedResources 注解导致
// 流程 :
C160- AbstractBeanDefinitionReader
M- loadBeanDefinitions
- ((ResourcePatternResolver) resourceLoader).getResources(location)
?- 注意 , 这里的 Resources 仍然是 pring-common.xml 这个对象
// 后续继续调用 XmlBeanDefinitionReader , 这里就不详细说了
PS: Что касается других, которые не являются репрезентативными, я не буду вдаваться в подробности.
3. Система документов
При загрузке юниформ-ресурса тип xml в нем будет обрабатываться как объект Document
Сканирование документов относится к сканированию системы документов, которое в основном используется при настройке бинов в xml.
PS: Скажу вам, в первые дни я тоже думал, что конфигурация XML устарела и устаревший метод, но теперь у меня другое ощущение, по сравнению с методом конфигурации, его структура более понятна и он не сложен в использовании .
Функция системы документов
Давайте взглянем на общие функции методов Doument:
эффект: используется для обработки объектов типа документа Document, включая .xml, .dto, .schemas и т. д.
источник: Метод XmlBeanDefinitionReader#doLoadDocument(InputSource inputSource, Resource resource)
- Этот метод делает 2 вещи
- Вызовите метод #getValidationModeForResource(ресурс ресурса), чтобы получить режим проверки указанного ресурса (xml).
- Вызовите DocumentLoader#loadDocument, чтобы получить экземпляр XML-документа.
C25- DocumentLoader : 获取 Document 的策略,由接口 org.springframework.beans.factory.xml.DocumentLoader 定义
P- inputSource 方法参数,加载 Document 的 Resource 资源。
P- entityResolver 方法参数,解析文件的解析器。
P- errorHandler 方法参数,处理加载 Document 对象的过程的错误。
P- validationMode 方法参数,验证模式。
P- namespaceAware 方法参数,命名空间支持。如果要提供对 XML 名称空间的支持,则需要值为 true 。
C26- DefaultDocumentLoader : DocumentLoader 的默认实现类
M26_01- loadDocument
- 首先,调用 #createDocumentBuilderFactory(...) 方法,创建 javax.xml.parsers.DocumentBuilderFactory 对象
- DocumentBuilderFactory.newInstance(); -- 创建 DocumentBuilderFactory
- factory.setNamespaceAware(namespaceAware); -- 设置命名空间支持
- 调用 #createDocumentBuilder 方法,创建 javax.xml.parsers.DocumentBuilder 对象
- 创建 DocumentBuilder 对象
- 设置 EntityResolver 属性
- 设置 ErrorHandler 属性
- 调用 DocumentBuilder#parse(InputSource) 方法,解析 InputSource ,返回 Document 对象
// XmlBeanDefinitionReader :
M- getEntityResolver() : 返回指定的解析器,如果没有指定,则构造一个未指定的默认解析器
-1 ResourceLoader resourceLoader = getResourceLoader();
IF-2 resourceLoader != null
- this.entityResolver = new ResourceEntityResolver(resourceLoader);
ELSE-2
- this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
Отслеживание сканирования документов:
// 起点 : Document 的起点是 , 这里会通过一个 Resource 加载对于的 xml , 将 XML 转换为 Document
C- ConfigurationClassBeanDefinitionReader
M- loadBeanDefinitionsFromImportedResources
// 中间的逻辑比较简单 , 我们直接从 XmlBeanDefinitionReader 开始看
C21- XmlBeanDefinitionReader
M21_01- doLoadBeanDefinitions(InputSource inputSource, Resource resource)
- 调用 doLoadDocument , 将 Resource 转换为 Document -> M23_01
- 调用 registerBeanDefinitions(doc, resource) 注册Bean
M21_02- doLoadDocument
- documentLoader.loadDocument : loader 加载
C- DocumentLoader
C23- DefaultDocumentLoader
I- DocumentLoader
M23_01- loadDocument(InputSource inputSource, EntityResolver entityResolver,ErrorHandler errorHandler, int validationMode, boolean namespaceAware)
- createDocumentBuilderFactory 创建一个 DocumentBuilderFactory -> M23_02
- 通过 DocumentBuilderFactory 创建一个 DocumentBuilder -> M23_03
- DocumentBuilder parse 方法解读 Document
M23_02- createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
- 通过 newInstance 生成 DocumentBuilderFactory
- 为 DocumentBuilderFactory 设置 NamespaceAware , Validating , 以及 Attribute
?- 注意 , 这里会判断 validationMode 类型来设置
M23_03- createDocumentBuilder(DocumentBuilderFactory factory, EntityResolver entityResolver, ErrorHandler errorHandler)
- 通过传入的工厂生成 DocumentBuilder
- 为 DocumentBuilder 设置 EntityResolver 和 ErrorHandler
// M23_01 补充
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
return builder.parse(inputSource);
}
// M23_02 补充
protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware){
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(namespaceAware);
if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
factory.setValidating(true);
if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
factory.setNamespaceAware(true);
factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
//.... 省略catch
}
}
return factory;
}
// N23_03
protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory,
@Nullable EntityResolver entityResolver, @Nullable ErrorHandler errorHandler)
throws ParserConfigurationException {
DocumentBuilder docBuilder = factory.newDocumentBuilder();
if (entityResolver != null) {
docBuilder.setEntityResolver(entityResolver);
}
if (errorHandler != null) {
docBuilder.setErrorHandler(errorHandler);
}
return docBuilder;
}
DocumentBuilder
DocumentBuilder 是一个抽象类 , 其主要 实现是 DocumentBuilderImpl
C24- DocumentBuilder
F- DOMParser domParser;
F- EntityResolver fInitEntityResolver
F- ErrorHandler fInitErrorHandler
MC- DocumentBuilderImpl
M24_01- parse
- domParser.parse(is)
- domParser getDocument 获得 Document
// 这里涉及到 com.sun.org.apache.xerces.internal.parsers.DOMParser 对象
C- DOMParser
?- 用于对 DOM 类型解析处理
Полная блок-схема обработки документов
// Step 1 : ConfigurationClassBeanDefinitionReader # loadBeanDefinitions
?- 用于加载 class类上面的 classpath load
// Step 2 : AbstractBeanDefinitionReader # loadBeanDefinitions
?- 开始加载 xml 文件
// Step 3 : XmlBeanDefinitionReader # loadBeanDefinitions
?- 处理加载的 resource 对象 , xml resource 的加载可以看上文
// Step 4 : 主要处理流程开始
C21- XmlBeanDefinitionReader
M21_01- doLoadBeanDefinitions
- doLoadDocument(inputSource, resource) -> M21_02
M21_02- doLoadDocument
C26- DefaultDocumentLoader : DocumentLoader 的默认实现类
M26_01- loadDocument
C24- DocumentBuilder
M24_01- parse
Расширить объект EntityResolver
Объект EntityResolver используется для анализа документа, и это общие:
Справочная документация @cmsblogs.com/?p=2695
- ResourceEntityResolver: наследуется от EntityResolver и разрешает ссылки на сущности через ResourceLoader.
- DelegatingEntityResolver: реализация EntityResolver, которая соответственно прокси-сервер BeansDtdResolver для dtd и PluggableSchemaResolver для схем xml.
- BeansDtdResolver : Преобразователь dtd компонента Spring. Реализация EntityResolver для загрузки dtd из пути к классам или файла jar.
- PluggableSchemaResolver: разрешает URL-адреса схемы в локальные ресурсы пути к классам, используя последовательность файлов карты.
protected EntityResolver getEntityResolver() {
if (this.entityResolver == null) {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader != null) {
this.entityResolver = new ResourceEntityResolver(resourceLoader);
}else {
this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
}
}
return this.entityResolver;
}
Дополнительные функции документа
Документ в основном предназначен для интерпретации XML как читаемых объектов.
Дополнение DTD и XSD
Справочная документация @cmsblogs.com/?p=2688, рекомендуется посмотреть оригинальную версию, вот несколько ключевых ссылок
DTD(Document Type Definition), определение типа документа, представляет собой механизм проверки XML-файлов и является частью XML-файла.
DTD — это эффективный способ проверки правильно сформированного XML-документа, который определяет элементы, атрибуты, расположение, тип содержимого элементов и иерархическую структуру связанных XML-документов.Фактически DTD эквивалентен «словарному запасу» и «грамматике» в XML., мы можем сравнить файл XML с файлом DTD, чтобы увидеть, соответствует ли документ спецификации и правильно ли используются элементы и теги. Чтобы использовать DTD в Spring, вам нужно объявить в заголовке XML-файла Spring:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
DTD способствовал развитию XML на определенном этапе, но у него есть некоторые недостатки:
- Он не использует формат XML, а сам определяет набор форматов, который менее пригоден для повторного использования, чем синтаксический анализатор;
- Не существует стандартного интерфейса программирования для создания и доступа к DTD, что затрудняет простой анализ документов DTD парсерами.
- DTD имеют меньше ограничений на тип элементов, другие ограничения также называются слабыми.
- DTD имеет плохую масштабируемость.
- Документы DTD на основе регулярных выражений имеют ограниченные описательные возможности.
XSD имеет следующие преимуществаВ ответ на дефекты DTD W3C представил XSD в 2001 году. XSD (определение схем XML) — это язык схем XML. XML-схема сама по себе является документом XML и использует синтаксис XML, поэтому она может легко анализировать документы XSD.
- XML-схема основана на XML и не имеет специального синтаксиса.
- XML-схему можно анализировать и обрабатывать как любой другой XML-документ.
- XML-схема предоставляет более богатые типы данных, чем DTD.
- XML-схема обеспечивает расширяемую модель данных.
- XML-схема поддерживает комплексные пространства имен
- XML-схема поддерживает группы атрибутов.
Различные режимы проверки анализируются с использованием разных парсеров:
Место проверки для ValidationMode
C21- XmlBeanDefinitionReader
M21_02- doLoadDocument -> PS:M21_02_01
// PS:M21_02_01 此处获取了 ValidationMode
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,getValidationModeForResource(resource), isNamespaceAware());
protected int getValidationModeForResource(Resource resource) {
int validationModeToUse = getValidationMode();
if (validationModeToUse != VALIDATION_AUTO) {
return validationModeToUse;
}
int detectedMode = detectValidationMode(resource);
if (detectedMode != VALIDATION_AUTO) {
return detectedMode;
}
return VALIDATION_XSD;
}
// 常量
/**
* Indicates that the validation mode should be auto-guessed, since we cannot find
* a clear indication (probably choked on some special characters, or the like).
*/
public static final int VALIDATION_AUTO = 1;
/**
* Indicates that DTD validation should be used (we found a "DOCTYPE" declaration).
*/
public static final int VALIDATION_DTD = 2;
/**
* Indicates that XSD validation should be used (found no "DOCTYPE" declaration).
*/
public static final int VALIDATION_XSD = 3;
Суммировать
Сканирование и сбор ресурсов и документов является основой всего.Когда они полностью собраны, можно начать загрузку связанных классов.