Концепция IOC
IoC (инверсия управления, инверсия управления) является ядром Spring во всем. Так называемый IoC для фреймворка Spring означает, что Spring отвечает за управление жизненным циклом объектов и связью между объектами. Все классы будут зарегистрированы в контейнере Spring, сообщая Spring, кто вы и что вам нужно, а затем Spring возьмет на себя инициативу, чтобы дать вам то, что вы хотите, когда система запустится в соответствующее время, а также даст вам других, которые нужна тебе вещь. Созданием и уничтожением всех классов управляет Spring, а это значит, что уже не объект ссылается на него, а Spring управляет жизненным циклом объекта. Для конкретного объекта раньше он управлял другими объектами, но теперь все объекты управляются пружиной, поэтому это называется инверсией управления.
Одним из основных моментов IoC является динамическое предоставление объекту других необходимых ему объектов во время работы системы (время выполнения). Это достигается с помощью DI (внедрение зависимостей). Например, для работы с базой данных требуется объект A. В прошлом нам всегда приходилось писать код в A, чтобы получить объект Connection. С Spring нам нужно только сообщить Spring, что Connection требуется в A. Что касается того, как построить это Соединение, когда его построить, А не нужно знать. Когда система работает, Spring создаст Connection в соответствующее время, а затем введет его в A как инъекцию, тем самым завершив контроль отношений между различными объектами. А должен зависеть от Соединение может работать нормально, и это соединение вводится в A с помощью spring, и отсюда происходит название внедрения зависимостей. Так как же реализован DI? Важной функцией после Java 1.3 является отражение, которое позволяет программам динамически генерировать объекты, выполнять методы объектов и изменять свойства объектов во время выполнения Spring реализует внедрение через отражение.
Процесс изменения создания объекта
Как видно из приведенного выше рисунка, поведение, которое ранее активно создавалось клиентом, было изменено и создано контейнером IoC. В традиционном программировании на Java SE мы напрямую создаем объекты через new внутри объекта, а программа активно создает зависимые объекты; при этом IoC имеет специальный контейнер для создания этих объектов, то есть Ioc-контейнер управляет созданием объектов; IoC-контейнер управляет созданием объектов объект, управлять чем? Он в основном контролирует получение внешних ресурсов (не только объектов, включая файлы и т. д.); традиционные приложения активно контролируются нами в объекте для непосредственного получения зависимых объектов, то есть прямого вращения; в то время как обратное вращение создается контейнером. Внедрение зависимых объектов, зачем реверсировать? Поскольку контейнер помогает нам находить и внедрять зависимые объекты, объект только пассивно принимает зависимые объекты, поэтому он инвертируется; какие аспекты реверсируются? Приобретение зависимых объектов отменяется.
Весенняя структура IOC
Когда Spring запускается, он считывает информацию о конфигурации Bean, предоставленную приложением, и создает соответствующий реестр конфигурации Bean в контейнере Spring, а затем создает экземпляр Bean в соответствии с этим реестром, собирает зависимости между bean-компонентами и предоставляет верхний уровень. Приложение предоставляет готовую к работе среду.
Буферный пул бинов
Spring описывает зависимости между bean-компонентами и bean-компонентами через файл конфигурации и использует функцию отражения языка Java для создания экземпляров bean-компонентов и установления зависимостей между bean-компонентами. Контейнер Spring IoC также предоставляет расширенные услуги, такие как кэширование экземпляра компонента, управление жизненным циклом, прокси-сервер экземпляра компонента, публикация событий и загрузка ресурсов на основе выполнения этих базовых задач.
Структура BeanFactory
-
BeanDefinitionRegistry: каждый элемент узла в файле конфигурации Spring представлен объектом BeanDefinition в контейнере Spring, который описывает информацию о конфигурации компонента. Интерфейс BeanDefinitionRegistry предоставляет метод ручной регистрации объектов BeanDefinition в контейнере.
-
Интерфейс BeanFactory расположен в верхней части дерева структуры классов. Его основным методом является getBean(String beanName), который возвращает из контейнера Bean с определенным именем. Функции BeanFactory постоянно расширяются за счет других интерфейсов:
-
ListableBeanFactory: этот интерфейс определяет несколько методов доступа к основной информации о bean-компонентах в контейнере, таких как проверка количества bean-компонентов, получение имени конфигурации определенного типа bean-компонентов и проверка того, включен ли определенный bean-компонент в контейнер;
-
HierarchicalBeanFactory: интерфейс каскадного IoC-контейнера родитель-потомок, дочерний контейнер может получить доступ к родительскому контейнеру через интерфейсный метод; через интерфейс HierarchicalBeanFactory контейнер IoC Spring может установить контейнерную систему, связанную с иерархией родитель-потомок, дочерний контейнер может получить доступ к bean-компонентам в родительском контейнере, но к родительскому контейнеру нельзя получить доступ к bean-компонентам подконтейнеров. Spring использует родительско-дочерние контейнеры для реализации многих функций.Например, в Spring MVC компоненты уровня представления расположены в дочернем контейнере, а компоненты бизнес-уровня и уровня сохраняемости находятся в родительском контейнере. Таким образом, уровень представления Компоненты могут ссылаться на компоненты бизнес-уровня и уровня сохраняемости, но компоненты бизнес-уровня и уровня сохранения не могут видеть компоненты уровня представления.
-
ConfigurableBeanFactory: это важный интерфейс, который расширяет возможности настройки контейнера IoC.Он определяет такие методы, как установка загрузчиков классов, редакторов свойств и постпроцессоров инициализации контейнера;
-
AutowireCapableBeanFactory: определяет метод автоматической сборки бинов в контейнере по определенным правилам (таким как сопоставление по имени, сопоставление по типу и т. д.);
-
SingletonBeanRegistry: определяет методы, которые позволяют регистрировать одноэлементные компоненты в контейнере во время выполнения;
Инициализация контейнера IoC
ApplicationContext является производным от BeanFactory и предоставляет более практичные функции, ориентированные на приложения.
В BeanFactory многие функции должны быть реализованы программно, тогда как в ApplicationContext это можно реализовать с помощью конфигурации.
ApplicationContext
ApplicationContext наследует интерфейсы HierarchicalBeanFactory и ListableBeanFactory и на этой основе также расширяет функции BeanFactory через несколько других интерфейсов:
-
ClassPathXmlApplicationContext: загружать файлы конфигурации из пути к классам по умолчанию.
-
FileSystemXmlApplicationContext: загружать файлы конфигурации из файловой системы по умолчанию.
-
ApplicationEventPublisher: позволить контейнеру иметь функцию публикации событий контекста приложения, включая события запуска контейнера, события завершения работы и т. д. Bean-компоненты, реализующие интерфейс прослушивателя событий ApplicationListener, могут получать события контейнера и реагировать на них. В классе абстрактной реализации ApplicationContext AbstractApplicationContext мы можем обнаружить, что существует ApplicationEventMulticaster, который отвечает за сохранение всех прослушивателей для уведомления этих прослушивателей событий, когда контейнер генерирует контекстные события.
- MessageSource: обеспечивает функцию интернационализированного доступа к сообщениям i18n для приложений;
- ResourcePatternResolver: все классы реализации ApplicationContext реализуют функции, аналогичные PathMatchingResourcePatternResolver, которые могут загружать файлы конфигурации Spring через префиксные пути к файлам ресурсов в стиле Ant.
- LifeCycle: этот интерфейс добавлен в Spring 2.0.Этот интерфейс предоставляет два метода, start() и stop(), которые в основном используются для управления процессом асинхронной обработки. При конкретном использовании этот интерфейс реализуется как ApplicationContext, так и конкретными bean-компонентами.ApplicationContext будет передавать информацию о запуске/остановке всем bean-компонентам в контейнере, реализующем этот интерфейс, для управления и контроля JMX, планирования задач и других целей.
- ConfigurableApplicationContext расширяет ApplicationContext, добавляя два новых основных метода: refresh() и close(), которые дают ApplicationContext возможность запускать, обновлять и закрывать контексты приложения. Когда контекст приложения закрыт, вызовите refresh(), чтобы запустить контекст приложения.В уже запущенном состоянии вызовите refresh(), чтобы очистить кеш и перезагрузить информацию о конфигурации, и вызовите close(), чтобы закрыть контекст приложения. Эти методы интерфейса упрощают контроль и управление контейнерами, но нам, как разработчикам, не нужно слишком заботиться об этих методах.
Жизненный цикл фасоли
1. Когда вызывающая сторона запрашивает bean-компонент из контейнера через getBean(beanName), если контейнер регистрирует интерфейс org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor, перед созданием экземпляра bean-компонента будет вызываться метод интерфейса postProcessBeforeInstantiation();
2. Вызовите конструктор Bean или фабричный метод, чтобы создать экземпляр Bean в соответствии с конфигурацией;
3. Если контейнер регистрирует интерфейс InstantiationAwareBeanPostProcessor, после создания экземпляра bean-компонента вызовите метод интерфейса postProcessAfterInstantiation(), и здесь вы можете немного «нарядить» созданный объект;
4. Если bean-компонент сконфигурирован с информацией о свойствах, контейнер начинает устанавливать значение конфигурации для свойства, соответствующего bean-компоненту на этом шаге, но перед установкой каждого свойства сначала будет вызываться метод postProcessPropertyValues() интерфейса InstantiationAwareBeanPostProcessor;
5. Вызовите метод установки свойства bean-компонента, чтобы установить значение свойства;
6. Если bean-компонент реализует интерфейс org.springframework.beans.factory.BeanNameAware, метод интерфейса setBeanName() будет вызываться для установки соответствующего имени bean-компонента в файле конфигурации для bean-компонента;
7. Если Бин реализует интерфейс org.springframework.beans.factory.BeanFactoryAware, метод интерфейса setBeanFactory() будет вызываться для установки экземпляра контейнера BeanFactory в Бин;
8. Если BeanFactory оснащен постпроцессором org.springframework.beans.factory.config.BeanPostProcessor, он будет вызывать метод интерфейса Object postProcessBeforeInitialization(Object bean, String beanName) BeanPostProcessor для обработки bean-компонента. Входной bean-компонент — это bean-компонент, который в данный момент обрабатывается, beanName — это имя конфигурации текущего bean-компонента, а возвращаемый объект — это обработанный bean-компонент. Боб. Пользователи могут использовать этот метод для выполнения специальной обработки определенных bean-компонентов и даже для изменения поведения bean-компонентов. BeanPostProcessor занимает важное место в среде Spring, предоставляя контейнеру точку входа для последующей обработки bean-компонентов. как АОП, динамические прокси и др.) реализованы через BeanPostProcessor;
9. Если Бин реализует интерфейс InitializingBean, будет вызван метод интерфейса afterPropertiesSet();
10. Если метод инициализации определен через атрибут init-method, этот метод будет выполнен;
11. Постпроцессор BeanPostProcessor определяет два метода: один — вызов postProcessBeforeInitialization() на шаге 8; другой — метод Object postProcessAfterInitialization(Object bean, String beanName), который вызывается в это время, и контейнер получает возможность обрабатывать bean-компонент. снова возможность обработки;
12. Если область действия бина указана как scope="prototype", бин возвращается вызывающей стороне, и вызывающая сторона отвечает за управление последующей жизнью бина, а Spring больше не управляет жизненным циклом бина ; если для области задано значение scope="singleton" ", поместите компонент в пул кеша контейнера Spring IoC и верните ссылку на компонент вызывающей стороне, а Spring продолжит управлять последующей жизнью этих компонентов;
13. Для bean-компонентов с scope = «singleton» при закрытии контейнера Spring запустит управление последующим жизненным циклом bean-компонента.Во-первых, если bean-компонент реализует интерфейс DisposableBean, будет вызываться метод интерфейса afterPropertiesSet() , а релиз можно написать сюда Операции типа ресурсы, логгирование и т.д.;
14. Для bean-компонента с scope="singleton", если в атрибуте destroy-method указан метод уничтожения bean-компонента, Spring выполнит метод bean-компонента, чтобы завершить освобождение ресурсов bean-компонента.
Эти методы можно условно разделить на три категории:
-
Собственные методы Бина: например, вызов конструктора Бина для создания экземпляра Бина, вызов Сеттера для установки значения свойства Бина и методов, указанных в методе инициализации и методе уничтожения;
-
Методы интерфейса бобовых сил. Фасоль. Методы интерфейса.
-
Интерфейс сэкономный цикл. отражается на весенний контейнер предварительно идентифицирован. Когда весенний контейнер создает любую фасоль, эти постпроцессоры могут действовать, поэтому эти постпроцессоры глобальные. Конечно, пользователь может обработать задний процессор для обработки только бобов путем разумного письма.
Еще одно большое различие между ApplicationContext и BeanFactory заключается в том, что ApplicationContext будет использовать механизм отражения Java для автоматической идентификации BeanPostProcessor, InstantiationAwareBeanPostProcessor и BeanFactoryPostProcessor, определенных в файле конфигурации, и автоматически регистрировать их в контексте приложения; последнее необходимо сделать вручную в коде. addBeanPostProcessor() для регистрации. Вот почему мы обычно используем Одна из причин редкого использования ApplicationContext и BeanFactory.
Рабочий механизм контейнера IOC
процесс запуска контейнера
Процесс запуска контейнера Spring и контейнера SpringMVC в веб-среде:
-
Для веб-приложения оно развертывается в веб-контейнере, а веб-контейнер предоставляет глобальную контекстную среду, которая является ServletContext, которая обеспечивает хост-среду для последующего весеннего контейнера IoC;
-
ContextLoaderListener (или ContextloaderServlet) будет предоставлен в Web.xml. Когда веб-контейнер запускается, событие инициализации контейнера будет запущено. В это время контекстно-процессорносистенер будет прослушивать это событие, и его контекстенициализованный метод будет вызван. В этом методе пружина будет инициализировать контекст запуска, который называется корнем контекста, который называется root Контекст, а именно webapplyingcationContext, который представляет собой класс интерфейса, быть точным, его фактический класс реализации - XMLWebaplicationContext. Это контейнер IOC Spring, и конфигурация ее соответствующего определения компонента компонента определяется тегом контекстно-параметра в Web.xml. После инициализации контейнера IOC контейнер для пружины использует webapplyctionContcontext.rootwebaplicationContextAttribute в качестве клавиши атрибута и сохраняет его в сервелевом элементе для легкого доступа;
-
После того, как прослушиватель contextLoaderListener инициализирован, он начинает инициализировать сервлет, настроенный в web.xml. Этот сервлет может быть настроен с несколькими.В качестве примера возьмем наиболее распространенный DispatcherServlet (Spring MVC).Этот сервлет на самом деле является стандартным интерфейсом Пересылать, сопоставлять и обрабатывать каждый запрос сервлета. Когда контекст DispatcherServlet инициализирован, он устанавливает свой собственный контейнер контекста IoC для хранения bean-компонентов, связанных с spring mvc Классом реализации по умолчанию контекста, удерживаемого этим сервлетом, также является XmlWebApplicationContext. При установлении собственного контекста ввода-вывода DispatcherServlet использует WebApplicationContext.ROOTWEBAPLICATIONCONTEXTATTRIBUTE для получения предыдущего корневого контекста (т. е. WebApplicationContext) из ServletContext в качестве родительского контекста своего собственного контекста (т. е. XmlWebApplicationContext, инициализированного на шаге 2 в качестве собственного родительского контейнера). После того, как у вас есть этот родительский контекст, инициализируйте контекст, который он содержит (этот DispatcherServlet инициализирует свой собственный контекст в своем методе initStrategies, что можно увидеть в его методе initStrategies. Примерная работа заключается в инициализации сопоставления процессора, разрешения просмотра и т. д.). После инициализации spring использует атрибут, связанный с именем сервлета (здесь не просто сервлет с именем Key, а через некоторое преобразование) в качестве атрибута Key, а также сохраняет его в ServletContext для последующего использования. Таким образом, каждый сервлет содержит свой собственный контекст, то есть имеет свое собственное независимое пространство компонентов, и каждый сервлет совместно использует одни и те же компоненты, то есть компоненты, определенные корневым контекстом.
Процесс загрузки бина
Гениальность Spring заключается в том, что он использует множество интерфейсов для создания чертежей всех устройств, строит скелет Spring, а затем выводит слой за слоем через систему наследования, постоянно обогащая и, наконец, превращая Spring в полноценную структуру из плоти и крови. Итак, при взгляде на исходный код фреймворка Spring есть два четко видимых контекста:
1) Уровень интерфейса описывает важные компоненты контейнера и взаимодействие между компонентами;
2) Система наследования постепенно реализует функции компонентов.
Интерфейсный слой четко описывает функции высокого уровня пружинного каркаса, а рамочный контекст собирается появиться. С абстрактным описанием интерфейсного слоя, не только сама весна может предоставить конкретные реализации, но любая сторонняя организация также может предоставлять различные реализации. Можно сказать, что идеальный интерфейсный слой весной обеспечивает масштабируемость каркаса. Постепенное расширение системы вертикальной наследования реализует функции рамки шаг за шагом. Эта схема реализации гарантирует, что структурные функции не будут накапливаться на некоторых классах, что приводит к чрезмерной логической нагрузке кода, а сложность структуры прекрасно разлагается Отказ
Компоненты Spring можно разделить на две категории в зависимости от их роли:
1) Материальные компоненты: Resource, BeanDefinition, PropertyEditor, окончательный Bean и т. д., это компоненты, обрабатываемые и потребляемые в процессе обработки, точно так же, как материалы, обрабатываемые на сборочной линии;
BeanDefinition: Spring преобразует информацию о конфигурации в файле конфигурации во внутреннее представление контейнера через BeanDefinition и регистрирует эти BeanDefinitions в BeanDefinitionRegistry. Последующие операции контейнера Spring считывают информацию о конфигурации непосредственно из BeanDefinitionRegistry.
2) Компоненты обрабатывающего оборудования: ResourceLoader, BeanDefinitionReader, BeanFactoryPostProcessor, InstantiationStrategy и BeanWrapper и другие компоненты похожи на обрабатывающее оборудование в разных звеньях сборочной линии, обрабатывающие материальные компоненты.
-
InstantiationStrategy: отвечает за создание экземпляров операций Bean, что эквивалентно новой функции в языке Java, и не будет участвовать в настройке свойств Bean. Работа по заполнению атрибутов оставлена для завершения BeanWrapper.
-
BeanWrapper: наследует интерфейсы PropertyAccessor и PropertyEditorRegistry.BeanWrapperImpl инкапсулирует два типа компонентов: инкапсулированный целевой компонент и набор редакторов свойств для установки свойств компонента; он имеет тройную идентичность: оболочка компонента, средство доступа к свойствам, поверхность регистрации редактора свойств.
- Propertyaccessor: определяет способ доступа к свойству бобов. PropertyEditoreGistry: регистрационная форма для редактора недвижимости
Полный поток заданий Bean
обработать
1. ResourceLoader загружает информацию о конфигурации Spring с носителя и использует Resource для представления ресурсов этого файла конфигурации;
2. BeanDefinitionReader считывает ресурс файла конфигурации, на который указывает Resource, а затем анализирует файл конфигурации. Каждый из файлов конфигурации анализируется в объект BeanDefinition и сохраняется в BeanDefinitionRegistry;
3. Контейнер сканирует BeanDefinition в BeanDefinitionRegistry, использует механизм отражения Java для автоматической идентификации компонентов постпроцессора Bean Factory (реализуя интерфейс BeanFactoryPostProcessor), а затем вызывает эти постпроцессоры Bean Factory для обработки BeanDefinition в BeanDefinitionRegistry. В основном выполните следующие две задачи:
1) Проанализируйте теги элементов, которые используют заполнители, чтобы получить окончательное значение конфигурации, что означает обработку некоторых полуфабрикатов объектов BeanDefinition и получение готовых объектов BeanDefinition;
2) Просканировать BeanDefinition в BeanDefinitionRegistry, найти все bean-компоненты редактора свойств (beans, реализующие интерфейс java.beans.PropertyEditor) через механизм отражения Java, и автоматически зарегистрировать их в реестре редактора свойств контейнера Spring ( PropertyEditorRegistry );
4. Весенний контейнер вынимает обработанную фасольную обработку из BeanDefinitionRiCistryRegistry и вызывает инсалиционную структуру, чтобы начать работу по созданию геологоразведателя;
5. При создании экземпляра компонента контейнер Spring использует BeanWrapper для инкапсуляции компонента. BeanWrapper предоставляет множество методов для работы с компонентом с использованием механизма отражения Java. Он будет комбинировать BeanDefinition компонента и редактор свойств в контейнере для завершения настройки компонента. характеристики;
6. Используйте зарегистрированный в контейнере постпроцессор Бина (Бин, реализующий интерфейс BeanPostProcessor) для выполнения последующей обработки Бина, завершившего работу по установке атрибутов, и непосредственной сборки готового Бина.
Суммировать
Контейнер Spring IOC в основном включает BeanFactory в нижней части системы наследования, ApplicationContext и WebApplicationContext на высоком уровне. Бобы имеют свой жизненный цикл.
Принцип запуска контейнера: контейнер IOC приложения Spring запускается и загружается через мониторинг сервлета или прослушивателя Tomcat; контейнер Spring MVC загружается DispatchServlet в качестве записи; контейнер Spring является родительским контейнером контейнера Spring MVC.
Принцип загрузки контейнера Bean:
BeanDefinitionReader считывает ресурс файла конфигурации, на который указывает Resource, а затем анализирует файл конфигурации. Каждый из файлов конфигурации анализируется в объект BeanDefinition и сохраняется в BeanDefinitionRegistry;
Контейнер сканирует BeanDefinition в BeanDefinitionRegistry, вызывает InstantiationStrategy для создания экземпляра Bean, использует BeanWrapper для завершения установки атрибута Bean;
Singleton Bean Cache Pool: Spring
Класс DefaultSingletonBeanRegistry предоставляет кеш для компонентов Bean с одним экземпляром, который представляет собой кеш, реализованный с помощью HashMap, и компоненты Bean с одним экземпляром хранятся в этом HashMap с beanName в качестве ключа.
Эта статья в основном воспроизведена изКраткое изложение принципов Spring IOC.