Базовыми функциями Spring являются IoC и AOP, а нашими bean-компонентами управляет Spring. Так как же Spring IoC генерирует эти bean-компоненты и как улучшает прокси-сервер AOP для указанного bean-компонента? Ответ кроется в процессе запуска Spring.
1. Spring IoC
1.1 Взгляд на Spring IoC с высоты птичьего полета
Для удобства здесь используется версия аннотации для запуска контейнера Spring IoC. Как показано ниже.
Здесь мы сначала говорим о резюме, а затем объясняем исходный код, сначала уточняем контекст, а затем углубляемся в детали, чтобы не запутаться в деталях.
Как показано на рисунке выше, процесс запуска Spring можно разделить на две части:
- Шаг 1: Разобрать в BeanDefinition: разобрать информацию об определении компонента в класс BeanDefinition.Независимо от того, определена ли информация о компоненте в xml или аннотирована аннотацией @Bean, ее можно преобразовать в класс BeanDefinition с помощью различных BeanDefinitionReaders.
- Существует два типа BeanDefinition, RootBeanDefintion и BeanDefinition. RootBeanDefinition находится на системном уровне и представляет собой 6 bean-компонентов, которые необходимо загрузить для запуска Spring. BeanDefinition — это Bean, который мы определяем.
- Шаг 2: Ссылаясь на информацию о классе, определенную BeanDefintion, создайте экземпляры компонентов через BeanFactory и сохраните их в кэше.
- BeanFactoryPostProcessor здесь является перехватчиком.После создания экземпляра BeanDefinition, BeanDefinition может быть изменен до того, как BeanFactory сгенерирует Bean.
- BeanFactory использует отражение для создания экземпляров bean-компонентов в соответствии с определением BeanDefinition.Процесс создания и инициализации bean-компонентов включает жизненный цикл bean-компонентов.Типичной проблемой является круговая зависимость bean-компонентов. Затем, перед созданием экземпляра bean-компонента, он решает, нуждается ли bean-компонент в улучшении, и решает, какой прокси использовать для создания bean-компонента.
Жизненный цикл Bean показан на рисунке ниже. Сначала вы можете получить представление. Перейдите к части исходного кода, а затем оглянитесь назад, чтобы увидеть жизненный цикл Bean.
1.2 Исходный код Spring IoC
Сейчас я использую исходный код Spring 5.2.6, разработанный с использованием полностью аннотированной версии Spring.
Первым шагом является создание нового контейнера.
Нажмите и посмотрите, вы можете увидеть, что есть три основных метода, пожалуйста, запомните эти три метода, this(); register(componentClasses); Refresh();
1.2.1 метод this()
Нажмите, чтобы ввести это, и увидите, что шесть RootBeanDefinitions зарегистрированы на внутреннем уровне, то есть BeanDefinition системного уровня.
Зайдя снова, вы увидите, что зарегистрированное BeanDefinition фактически помещено в кэш BeanFactory.
Возьмем в качестве примера класс ConfigurationClassPostProcessor, который на самом деле является перехватчиком BeanFactoryPostProcessor. Обратите внимание, что эта часть кода обратного вызова будет выполняться только в функции refresh(). Таким образом, упомянутый ниже BeanFactoryPostProcessor не будет выполняться, а будет выполняться в функции refresh().
ConfigurationClassPostProcessor перехватывает класс конфигурации и анализирует определение Bean внутри. Его метод перехвата проверяет, является ли класс классом конфигурации.
Затем проанализируйте класс конфигурации.
Разбор @Import и @Bean
1.2.2 Метод регистрации (классы компонентов)
Этот метод в основном предназначен для регистрации класса конфигурации, переданного новым AnnotationConfigApplicationContext(xxxConfiguration.class).
1.3 Метод обновления()
Это самый важный метод загрузки Spring. Нажмите, чтобы посмотреть. Среди них invokeBeanFactoryPostProcessor, как следует из названия, предназначен для вызова постпроцессора BeanFactory. registerBeanPostProcessors(beanFactory) регистрирует постпроцессоры бина. Постпроцессоры бина широко используются в Spring. Они могут перехватывать процессоры в процессе создания бина. Подобно BeanFactoryPostProcessor, они также являются перехватчиками.
Нажмите на этот метод, finishBeanFactoryInitialization(beanFactory). Он является важным методом инициализации бинов. Компоненты могут быть определены с помощью @Bean или инициализированы с помощью FactoryBean.
Нажмите getBean(beanName), чтобы увидеть, как создается компонент.В то же время это также жизненный цикл компонента.
см. метод createBean(beanName, mbd, args)
Процесс создания bean-компонента можно разделить на два этапа: создание экземпляра и инициализация. Создание экземпляра относится к созданию экземпляра компонента, а инициализация относится к заполнению (назначению свойств) свойств экземпляра компонента. Метод resolveBeforeInstantiation() выполняется до создания экземпляра компонента. Предоставляет постпроцессору компонента возможность вернуть прокси, и когда вы вызываете проксируемый компонент, вы фактически выполняете расширенный объект прокси.
Нажмите на метод doCreateBean. Вот жизненный цикл бина, такой как картинка, выпущенная в начале.
Жизненный цикл бина, вы можете видеть, что экземпляр создается на первом шаге
Нажмите на метод createBeanInstance, чтобы войти, и вы увидите, что объект bean наконец-то создан посредством отражения Java.
Нажмите на метод initializeBean для просмотра, и вы увидите, что он соответствует приведенной выше схеме жизненного цикла. Сначала проверьте интерфейс Aware, затем перейдите к методу предварительной обработки постпроцессора Bean, а затем вызовите метод инициализации.
жизненный цикл фасоли
На этом объяснение процесса запуска функции контейнера IoC компонента заканчивается.
Spring AOP
С точки зрения расширения прокси-сервера Spring, прежде чем мы увидим созданный bean-компонент в разделе контейнера IoC выше, мы фактически сначала определяем, нуждается ли bean-компонент в улучшении.Метод resolveBeforeInstantiation(beanName, mdbToUse).Обратите внимание, что этот метод находится перед bean-компонентом. То есть сначала определите, нужно ли создавать прокси, если нет, то создайте bean-компонент, в противном случае создайте прокси-объект.
Уже поздно, продолжение следует. Я напишу содержание части АОП завтра.
Я обновлю его.
Итак, как Spring Aop создает прокси?Давайте рассмотрим метод resolveBeforeInstantiation(beanName, bdbToUse).
Видно, что он вызывает метод постпроцессора бина InstantiationAwareBeanPostProcessor, судя по названию класса, он перехватывает фазу создания экземпляра бина, а не фазу инициализации. Нажмите, чтобы посмотреть, вы можете обнаружить, что он генерирует объект bean, вызывая метод обратного вызова InstantiationAwareBeanPostProcessor.
Вызовите метод postProcessBeforeInstantiation для создания объекта.
На этом пока остановитесь. Давайте посмотрим, как мы обычно используем Spring Aop.
Мы напишем аннотированный класс аспекта @Aspect и используем аннотацию @EnableAspectJAutoProxy для включения проксирования.
Щелкните, чтобы обнаружить, что он импортирует класс AspectJAutoProxyRegistrar в контейнер Spring.
Этот класс является классом ImportBeanDefinitionRegistrar.Поиск может обнаружить, что класс ImportBeanDefinitionRegistrar будет вызывать метод registerBeanDefinitions при анализе класса конфигурации.
Этот метод внедряет определение компонента класса AnnotationAwareAspectJAutoProxyCreator в контейнер.
Класс AnnotationAwareAspectJAutoProxyCreator представляет собой InstantiationAwareBeanPostProcessor.
На данный момент это согласуется с вышеизложенным.InstantiateAwareBeanPostProcessorвыполняется при создании экземпляра bean-компонента.Если есть возвращаемый объект, используется объект, в противном случае создается экземпляр. Таким образом, роль аннотации @EnableAspectJAutoProxy состоит в том, чтобы добавить в контейнер класс InstantiationAwareBeanPostProcessor, перехватить создание bean-компонентов и сгенерировать прокси-объекты.
Обработчик перехвата выглядит следующим образом: он создает прокси-объект и возвращает его.
Нажмите на метод createProxy(beanClass, beanName, SpecificInterceptor, targetSource) и проследите базовый код. Вы можете обнаружить, что существует два способа создания динамического прокси. Если класс является интерфейсом, используйте динамический прокси JDK, в противном случае используйте Cglib-прокси.
На этом часть Aop объяснения кода закончена.
Среди них проблема циклической зависимости IoC и дизайн цепочки перехватчиков Aop могут быть рекомендованы для просмотра исходного кода, если вам интересно.