Для программистов Write Java Spring стала одной из самых популярных сторонних сторонних структур с открытым исходным кодом, и мы полностью наслаждаемся дивиденцами весеннего контейнера IOC, чтобы привести в то же время, мы также должны рассмотреть весна этого завода, насколько большой из бобов Произведено, этот вопрос мы посмотрим на пример, чтобы обсудить процесс весеннего бона.
Здесь мы не будем подробно разбирать исходный код, а просто приведем, какие классы использует Spring при выполнении каких задач, и каковы конкретные обязанности этих классов.Если мы хотим разобраться во внутренностях и деталях инстанцирования Spring Bean, то исходный код вы можете посмотреть?Что касается конкретной и подробной информации о коде, вы можете проверить код классов, связанных с Spring.
два этапа
Прежде всего, давайте объявим, что Spring будет управлять зависимыми объектами один за другим как Beans, что также видно из файла конфигурации xml.
Контейнер Spring IOC подобен машине на сборочной линии, которая производит продукты, а bean-компоненты, созданные Spring, подобны изысканным продуктам, производимым в конце сборочной линии. Поскольку это машина, ее нужно запустить первой, и Spring не исключение. Поэтому жизнь Бина в целом можно разделить на два этапа:
- Фаза запуска контейнера
- Фаза пособия фасоли
Фаза запуска контейнера, чтобы сделать много предварительной работы, хорошо подготовлена для создания призванной фасоли, мы сначала посмотрим на фазовый контейнер запуска, сделали то, что предварительно нагревается.
Фаза запуска контейнера
1. Метаинформация конфигурации
Мы говорим, что контейнер Spring IOC отделяет создание экземпляров объектов от использования экземпляров объектов. Какие объекты нам нужны в нашем бизнесе, больше не зависят от нашего собственного ручного создания. Пока мы просим Spring, Spring даст нам требуемые объекты в виде инъекций.Зависимый объект. Однако, если вы этого не сделаете, я этого не сделаю. Кто-то должен это сделать. Поскольку мы передаем задачу создания объекта Spring, Spring должен знать некоторую необходимую информацию, необходимую для создания объекта. Эта необходимая информация может быть наиболее полным XML-файлом конфигурации, поддерживаемым Spring в прошлом, или другими формами дисковых файлов, такими как свойства, или это могут быть основные аннотации или даже прямое жесткое кодирование кода. Таким образом, необходимая информация, необходимая для создания объекта, называется метаинформацией конфигурации.
<bean id="role" class="com.wbg.springxmlbean.entity.Role">
<!-- property元素是定义类的属性,name属性定义的是属性名称 value是值
相当于:
Role role=new Role();
role.setId(1);
role.setRoleName("高级工程师");
role.setNote("重要人员");-->
<property name="id" value="1"/>
<property name="roleName" value="高级工程师"/>
<property name="note" value="重要人员"/>
</bean>
2. Определение компонента
Все мы знаем, что в мире Java все является объектом, аннотации, разбросанные по коду программы, и конфигурационная метаинформация, такая как xml или другие файлы, сохраненные на диске, всегда представлены в памяти в виде объекта, как и наш живой человек соответствует классу Person в мире Java, и Spring выбирает способ представления этой метаинформации конфигурации в памяти BeanDefination, Здесь мы не будем анализировать код BeanDefination, исходный код,Здесь нам просто нужно знать, что информация конфигурации существует в виде BeanDefination после того, как она загружается в память.
3, BeandefinaderReader
Вам должно быть очень любопытно, мы можем понять определения bean-компонентов в файле конфигурации xml в Spring, но как Spring понимает эту метаинформацию конфигурации? Это зависит от нашего BeanDefinationReader.
Разные BeanDefinationReaders похожи на братьев Hulu, каждый со своими навыками. Если мы хотим прочитать метаданные конфигурации xml, мы можем использовать XmlBeanDefinationReader. Если мы хотим прочитать файл конфигурации свойств, мы можем использовать для загрузки PropertiesBeanDefinitionReader. И если мы хотим прочитать метаинформацию конфигурации аннотаций, мы можем использовать AnnotatedBeanDefinitionReader для ее загрузки. Мы также можем легко настроить BeanDefinationReader для управления загрузкой метаинформации о конфигурации. Например, наша метаинформация о конфигурации существует за пределами Трех сфер, тогда мы можем настроить BeanDefinationReader из-за пределов Небесной сферы.
В общем, роль BeanDefinationReader состоит в том, чтобы загрузить метаинформацию о конфигурации и преобразовать ее в BeanDefination в виде памяти, которая существует в определенном месте, а где это место, не беспокойтесь, тогда смотрите вниз!
4. Реестр определений компонентов
На этом этапе мы, наконец, не пожалели усилий, чтобы загрузить метаинформацию о конфигурации, которая существует повсюду, в память и преобразовать ее в форму BeanDefination, чтобы, когда нам нужно создать экземпляр объекта, мы могли найти соответствующий BeanDefination а затем создать объект. Итак, когда нам нужен объект, где мы находим соответствующее BeanDefination? Как найти соответствующую связь или отношение сопоставления BeanDefination объекта с помощью идентификатора, определенного хранимым компонентом? Это ведет к BeanDefinationRegistry.
После того, как Spring загружает метаинформацию конфигурации в память для создания соответствующего BeanDefination через BeanDefinationReader, он регистрирует его в BeanDefinationRegistry. BeanDefinationRegistry — это большая корзина для хранения BeanDefination. Это также пара ключ-значение, которая сопоставляется с соответствующее BeanDefination.
5. BeanFactoryPostProcessor
BeanFactoryPostProcessor — это точка расширения, предоставляемая Spring на этапе запуска контейнера, которая в основном отвечает за изменение и замену BeanDefinations, зарегистрированных в BeanDefinationRegistry, в определенной степени. Например, некоторая информация о конфигурации, которая может быть изменена в нашей метаинформации о конфигурации, разбросана повсюду, что недостаточно гибко, и изменить соответствующую конфигурацию проблематично.В настоящее время мы можем использовать заполнители для настройки. Например, при настройке подключения к источнику данных Jdbc вы можете настроить его следующим образом:
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="maxIdle" value="${jdbc.maxIdle}"></property>
<property name="maxActive" value="${jdbc.maxActive}"></property>
<property name="maxWait" value="${jdbc.maxWait}"></property>
<property name="minIdle" value="${jdbc.minIdle}"></property>
<property name="driverClassName"
value="${jdbc.driverClassName}">
</property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
BeanFactoryPostProcessor внесет окончательную модификацию в BeanDefination, зарегистрированную в BeanDefinationRegistry, заменив заполнитель $ реальными данными в файле конфигурации.
На этом этапе вся фаза запуска контейнера завершена, и конечным продуктом фазы запуска контейнера является BeanDefination, зарегистрированный в BeanDefinationRegistry, который представляет собой предварительную работу, выполняемую Spring для создания экземпляра Bean. Давайте рассмотрим, что происходит на этапе запуска контейнера в виде схемы.
Фаза создания экземпляра компонента
Следует отметить, что существует разница во времени между фазой запуска контейнера и фазой создания экземпляра бина, и Spring передал это решение нашим программистам (это немного счастливо мгновенно!). Если мы выберем метод ленивой загрузки, то пока мы не обратимся к Spring, чтобы полагаться на экземпляр объекта, он будет существовать в форме BeanDefination в BeanDefinationRegistry, то есть Spring будет открывать соответствующий объект только тогда, когда нам нужно полагаться на него. объект, фаза создания экземпляра. Если мы не выберем метод ленивой загрузки, после завершения фазы запуска контейнера немедленно начнется фаза создания экземпляра компонента, и все настроенные компоненты будут созданы и сохранены путем неявного вызова метода getBean всех зависимых объектов.
Далее, давайте поговорим о вещах о процессе создания фасоли
1. Стратегия создания объекта
В это время Spring начал делать реальную работу.Создание объектов принимает режим стратегии.С помощью BeanDefination в нашем BeanDefinationRegistry мы можем использовать отражение для создания объектов или мы можем использовать байт-код CGlib для генерации и создания объектов. . В то же время мы можем гибко настроить, чтобы указать Spring, какую стратегию использовать для создания указанного объекта зависимости. Создание bean-компонентов в Spring — это классическое применение шаблона проектирования стратегии. В это время в памяти уже должен быть экземпляр конкретного зависимого объекта, который мы хотим, но развитие истории не так просто, как мы себе представляли.
Если вы не знаете о шаблоне стратегии, вы можете обратиться к соответствующим книгам или материалам в Интернете. Это содержание, связанное с шаблоном проектирования. шаблон дизайна не обсуждается.
2, BeanWrapper — оболочка объекта
Bean-компоненты в Spring не существуют в их исходной форме, поскольку в контейнере Spring IOC необходимо управлять несколькими типами объектов, чтобы унифицировать доступ к различным типам объектов.Весна дает все созданные экземпляры бобовЭтот слой является BEANWARAPPER (см. В соответствующем исходном коде, если вы заинтересованы в конкретном содержании BeanWRapper). Фаната фаната на самом деле является простой инкапсулированием API, связанных с отражением, что значительно упрощает использование верхнего слоя отражения для полной связанной бизнес-логики. Нам нужно получить свойства объекта и вызывать методы объекта, и теперь нет Нужно писать сложные apis отражения в дополнение к обработке куча хлопотных исключений, вы можете завершить связанные операции непосредственно через BeanWarapper, что не слишком круто.
3. Задайте свойства объекта
Объект, завернутый в BeanWrapper на предыдущем шаге, все еще является маленьким дочерним элементом, которому необходимо установить для него свойства и зависимые объекты.
- Для свойств базовых типов, если в метаинформации конфигурации есть конфигурация, то значение параметра в метаинформации конфигурации будет напрямую использоваться для присвоения значений.Даже если свойства базовых типов не имеют установленного значения, то спасибо в процессе создания экземпляра объекта JVM свойства по-прежнему могут иметь значение инициализации по умолчанию, равное нулю.
- Для свойств ссылочного типа Spring поместит все созданные объекты в структуру Map, при этом Spring проверит, попали ли зависимые объекты в область управления контейнера, то есть существует ли уже соответствующая карта в экземпляре объекта Map. Если есть, то внедрить напрямую, если нет, то Spring временно отложит процесс создания экземпляра объекта и вместо этого сначала создаст экземпляр зависимого объекта, а затем вернется, чтобы завершить процесс создания экземпляра объекта.
Вот классический вопрос в Spring: как Spring разрешает циклические зависимости?
Вот краткое упоминание, Spring решает циклическую зависимость через кеш третьего уровня и может решить только циклическую зависимость, введенную сеттером.Пожалуйста, подумайте, как это решить? Почему можно только сеттер инъекций? Подробности можно найти в соответствующих блогах, документах и книгах.
4. Проверьте интерфейсы, связанные с поддержкой
Мы знаем, что если мы хотим полагаться на связанные объекты в Spring и использовать связанные API-интерфейсы Spring, мы можем реализовать соответствующий интерфейс Aware, и контейнер Spring IOC автоматически внедрит для нас экземпляры связанных зависимых объектов. IOC-контейнеры Spring можно условно разделить на два типа: BeanFactory обеспечивает все функции, предусмотренные идеей IOC, а также интегрирует связанные функциональные модули, такие как АОП.Можно сказать, что BeanFactory — это базовый IOC-контейнер, предоставляемый Spring. ApplicationContext построен на BeanFactory и предоставляет такие функции, как публикация времени в контейнере, унифицированная стратегия загрузки ресурсов и поддержка интернационализации.Это более продвинутый контейнер IOC, предоставляемый Spring.
Сказав так много, я на самом деле хочу сказать, что для BeanFactory реализация этого шага заключается в том, чтобы сначала проверить соответствующий интерфейс Aware, а затем перейти к пулу объектов Spring (то есть к контейнеру, то есть к структуре Map), чтобы найти соответствующий экземпляр (например, для интерфейса ApplicationContextAware перейдите к экземпляру ApplicationContext), а это значит, что мы должны зарегистрировать соответствующий экземпляр в контейнере в файле конфигурации или с помощью аннотаций, чтобы BeanFactory мог автоматически внедрить его для нас.
Что касается ApplicationContext, поскольку он наследует ряд связанных интерфейсов, когда обнаруживаются связанные с Aware интерфейсы и требуются связанные зависимые объекты, ApplicationContext может внедрить себя в него.ApplicationContext реализует этот шаг через следующий материал — BeanPostProcessor.
Например, ApplicationContext наследуется от ResourceLoader и MessageSource, а затем, когда мы реализуем интерфейсы, связанные с ResourceLoaderAware и MessageSourceAware, мы можем внедрить себя в бизнес-объект.
5. Препроцессор BeanPostProcessor
Фу? Что такое pro с тех пор? Я считаю, что у людей, просто наблюдающих за этими двумя вещами, должно быть немного кружится голова.Я тоже был, но на самом деле это было по-разному, пока BeanFactoryPostProcessor существует на этапе запуска контейнера, а BeanPostProcessor существует на этапе создания экземпляра объекта, BeanFactoryPostProcessor FollowОбъект создается раньшеЭти конфигурации модифицируются и исправляются, а этап BeanPostProcessor фокусируется наПосле создания объектаРасширение функций, замена и другие операции, чтобы их было легко отличить.
BeanPostProcessor и BeanFactoryPostProcessor являются мощными точками расширения Spring в процессе производства Bean. Если вы все еще очень незнакомы с ним, то вы должны знать, что знаменитый АОП (аспектно-ориентированное программирование) в Spring фактически полагается на BeanPostProcessor для улучшения объекта Bean.
Предварительная обработка BeanPostProcessor позволяет нашим программистам изменять и заменять экземпляр Bean в определенной степени до того, как создаваемый экземпляр Bean будет помещен в контейнер.
Проверка applicationContext и автоматическая инъекция интерфейса Aware, упомянутого ранее, реализуются через BeanPostProcessor. На этом этапе Spring проверит, реализует ли Bean соответствующий интерфейс Aware. Если да, то внедрите себя в Bean. АОП в Spring реализуется на этом этапе, создавая прокси-объект для собственного объекта, а затем вызывая метод для исходного объекта, а затем используя тот же вызов метода прокси-объекта.
6. Пользовательская логика инициализации
После завершения всех приготовлений, если наш Bean все еще имеет определенную логику инициализации, то Spring позволит нам настроить нашу логику инициализации двумя способами: (1) InitializingBean (2) Настроить параметр init-method
Как правило, более гибко настроить метод init-method.
7. Постобработка BeanPostProcess
Подобно предварительной обработке, это последняя точка расширения, которую Spring оставляет нам после того, как пользовательская логика Bean также выполняется. Мы можем сделать некоторые расширения здесь, которые мы хотим.
8. Пользовательская логика уничтожения
Этот шаг соответствует пользовательской логике инициализации, и также есть два пути: (1) реализовать интерфейс DisposableBean (2) настроить параметр destroy-method.
Типичное приложение здесь, когда dataSource настроен, метод destroy является методом close() соединения с базой данных.
9,использовать
После вышеописанных процедур мы, наконец, можем насладиться удобством, которое принес Spring.В это время мы относимся к экземплярам Bean, сгенерированным Spring для нас, как к обычным объектам.Если вы считаете, что это неплохо, попробуйте!
10. Вызовите интерфейс уничтожения обратного вызова
После того, как bean-компонент Spring послужит нам, он скоро умрет (обычно при закрытии контейнера). Не забывайте о нашей пользовательской логике уничтожения. В это время Spring вызовет нашу пользовательскую логику уничтожения в методе обратного вызова. , а затем Bean закончил его славная жизнь, как это!
Давайте посмотрим вместе с помощью диаграммы, чтобы выполнить заказ на то, чтобы приспособиться к тому, как?
Следует отметить, что этап запуска экземпляра контейнера Bean-Bean между стадией и мостами, которые мы можем выбрать задержать стратегию загрузки настраиваемой конфигурации, если мы настраиваем бобную стратегию Lazy Lazy, поэтому мы используем только зависимые объекты в реальном времени, приведены только в реальном времени. фаза начнется в. И если мы не отключим ленивый загрузочный боб, то после фазы запуска контейнера он немедленно вступит в стадию пособия фасоли, через неявную вызов GetBean метод для создания связанного сочетания фанатов.
Если вы считаете, что это хорошо, пожалуйста, поставьте лайк Ваша поддержка и поощрение являются движущей силой моего творчества!