Основной интерфейс - BeanFactory
. Основной метод - getBean
. Его расширяют такие интерфейсы как:
ListableBeanFactory
для доступа к спискам экземпляров созданных bean’овHierarchicalBeanFactory
для организации иерархичных фабрик биновConfigurableBeanFactory
определяет методы, конфигурирующие бины
Этих интерфейсов бесчисленное множество. По отдельности они практически не используются, а служат для создания больших многофункциональных объектов фабрик. Для инициации загрузки необходим конфигурационный файл. За обработку источников конфигурации бинов отвечают BeanDefinition объекты:
PropertiesBeanDefinitionReader
для конфигурирования бинов в property файлахXmlBeanDefinitionReader
для конфигурирования бинов с помощью xml
Естественно, наиболее популярен XML BeanDefinition, но очевидно, что скоро и от XML откажутся, как от пережитка прошлого, в пользу Java синтаксиса. Но это будущее, а сейчас вершина FactoryBean
иерархии - XmlBeanFactory
. Этот объект определяет все специфичные для создания бинов с помощью xml конфигураций реализации, такие как XmlBeanDefinitionReader
. Настройки бина, обявленного в конфиге, хранятся в BeanDefinition объекте. Все эти объекты хранятся в реестре бинов - BeanDefinitionRegistry
.
Как же строятся бины?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Сразу же бросается в глаза некий утилитарный класс Assert
, который лишь визуально напоминает конструкцию языка java assert
. На этом сходство заканчивается, т.к. внутри все те же стандартные java исключения типа IllegalArgumentException
. С помощью метода getBeanNamesForType
получается массив всех имен бинов из реестра и отбираются только те, которые соответствуют по типу и другим логическим параметрам, что, к примеру, не позволяет создавать бины из абстрактных классов. Далее, если не нашлось ни одного имени, то пытаемся получить бин из родительской фабрики бинов. parentBeanFactory
задается в конструкторе фабрики при её создании. Если имен бинов найдено несколько, то значит конфиг некорректен. И тем не менее пытаемся в данном случае сузить круг поиска только бинами, которые помечены как внедряемые в другие классы.
Теперь, когда у нас есть имя бина и его тип, мы можем попытаться получить экземпляр бина. Метод создания бина достаточно большой (135 строк без сторонних используемых методов), поэтому покажу только кусочки. В первую очередь пытаемся получить объект, если это singleton и он был загружен ранее. Т.к. объект бина может быть фабрикой, то идет проверка на соответствие интерфейсу FactoryBean
. Если это действительно фабрика, то вызывается ее фабричный метод.
Порадовала проверка на параллельный запуск создания одного и того же бина в одном потоке.
1 2 3 |
|
Таким образом предотвращаются циклические ссылки. Статус создания того или иного бина хранится в NamedThreadLocal переменной.
Далее идут иерархические хитросплетения, которые сводятся к одному, к библиотке CGLib. С помощью неё создаются бины в spring’e.