1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/yoin-mvc-adapter-cloud

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
README.md 30 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 26.11.2024 03:25 18663c1

Проект введения

В последние годы технологии выбора веб-систем в основном были представлены архитектурой SpringMVC + Spring или Struts2 + Spring, представляющей собой монолитный фреймворк. В процессе итеративной разработки реальных проектов задачи являются срочными, а цикл разработки коротким, при этом навыки разработчиков различаются, и через несколько лет эксплуатации системы могут возникнуть следующие проблемы:

  • бизнес-логика переплетается, что затрудняет понимание после обслуживания несколькими людьми;
  • в процессе итерации существующий код связан с новым бизнесом, что приводит к невозможности очистки большого количества «мёртвого» кода;
  • исторические проблемы и архитектурные проблемы приводят к накоплению кода, делая систему всё более раздутой;
  • система имеет множество функций, и загрузка ресурсов при запуске занимает много времени, что не способствует гибкой разработке;
  • задачи планирования, расчёт бизнеса, сбор данных и другие задачи могут привести к сбою всей системы при возникновении аномалий в одном бизнесе.

В последнее время облачные нативные технологии, микросервисы Dubbo и архитектура SpringCloud становятся популярными. При переходе от монолитной системы к микросервисной архитектуре существуют следующие проблемы:

  1. Проблема стоимости миграции монолитной системы в микросервисную архитектуру: необходимо проанализировать бизнес, разделить бизнес, определить сервисы и провести техническую реконструкцию для перехода, что невозможно сделать за один шаг.
  2. Проблема обеспечения стабильной работы платформы во время процесса миграции: процесс миграции не может быть завершён в короткие сроки, существует состояние одновременного запуска монолитной архитектуры и микросервисной архитектуры, как обеспечить стабильность процесса миграции микросервисов в монолитной архитектуре и не дать пользователям почувствовать это?
  3. Во время процесса перехода монолитной архитектуры в микросервисную архитектуру также необходимо разрабатывать новые функции спроса, как поддерживать синхронизацию задач ипланов миграции, но не увеличивать объём работы по миграции?
  4. Как позволить двум архитектурам взаимодействовать друг с другом без препятствий, позволяя разработчикам незаметно взаимодействовать между двумя архитектурами?

На основе вышеуказанных проблем был разработан этот проект, позволяющий монолитной системе (не SpringBoot, не Dubbo, не SpringCloud) быстро и стабильно подключаться к облачной нативной микросервисной архитектуре, и постепенно объяснять в последующих архитектурах регистрацию сервисов, обнаружение сервисов и вызовы сервисов монолитной системы, а также имитировать процесс проектирования и идеи SpringCloud.

Применимые проекты Этот проект не является системной платформой, а относится к категории промежуточного программного обеспечения. На рынке уже есть много открытых проектов на основе SpringCloud, этот проект подходит для многолетних монолитных систем (не SpringBoot, не Dubbo, не SpringCloud), помогая старым проектам переходить на облачную нативную архитектуру и плавно переходить к микросервисной архитектуре. В ходе этого процесса будет объяснено, как использовать идеи и концепции исходного кода SpringCloud во время разработки проекта, а также некоторые из моих собственных интеграционных опытов. Изучение микросервиса, исследование исходного кода SpringCloud или Dubbo является абстрактным, и этот проект может помочь понять и применить его к реальным проектам, чтобы лучше понять основные механизмы SpringCloud.

  1. Традиционный проект MVC будет иметь следующие возможности:

    • способность компонентов автоматически зависеть;
    • возможность автоматической загрузки конфигурационных файлов в Bean;
    • способность к условной инъекции;
    • автоматическая регистрация сервисов MVC;
    • автоматическое обнаружение сервисов MVC.
    • реализация вызовов сервисов слоя услуг MVC (вызовы сервисов между MVC и между MVC и Cloud).
  2. Вы узнаете о следующих технологиях:

    • общее описание процесса Spring;
    • основные технологии SpringBoot, использование SPI для динамической загрузки компонентов;
    • базовая реализация условной инъекции SpringBoot;
    • базовая реализация префикса конфигурации файла SpringBoot;
    • внедрение контейнера пакета сканирования SpringBoot;
    • реализация ввода-вывода MVC, декодирования и кодирования SpringMVC;
    • регистрация сервиса SpringCloud;
    • обнаружение сервиса SpringCloud;
    • интеграция Feign для вызова RESTful сервиса.

Архитектура программного обеспечения Описание архитектуры программного обеспечения: архитектура проста и понятна, ниже приведена упрощённая архитектура интеграции традиционного MVC с возможностями SpringCloud, чем проще внутренняя структура, тем сложнее технические детали, которые необходимо реализовать, и они будут объяснены позже с точки зрения структуры технологии.

[|input_image_description|]

Объяснение модуля Модуль mvc-adapter-cloud включает в себя:

  • adapter-common — модуль адаптации MVC к облаку, который определяет общие компоненты регистрации и обнаружения сервисов, автоматическую зависимость, автоматическую конфигурацию и условную инъекцию;
  • adapter-consul — регистрация и обнаружение сервисов для адаптера Consul;
  • adapter-nacos — регистрация и обнаружение сервисов для адаптера Nacos;
  • adapter-openfeign — вызов сервисов между MVC или между MVC и облаком с использованием большой монолитной службы Feign;
  • Example — тестовый пример;
  • SpringCloud — пример SpringCloud;
  • CloudCommon — общий модуль SpringCloud;
  • CloudDemo — пример использования SpringCloud (CloudDemo);
  • DemoApi — интерфейс вызова CloudDemo;
  • DemoService — сервис CloudDemo;
  • CloudExample — второй пример использования SpringCloud (CloudExample);
  • ExampleApi — интерфейс вызова CloudExample;
  • ExampleService — сервис CloudExample.

SpringMVC — пример MVC:

  • MvcCommon — общий модуль MVC;
  • MvcDemo — первый пример MVC (MvcDemo);
  • MvcDemoApi — интерфейс вызова MvcDemo;
  • MvcDemoService — сервис MvcDemo;
  • MvcExample — второй пример MVC (MvcExample);
  • MvcExampleApi — интерфейс вызова MvcExample;
  • MvcExampleService — сервис MvcExample.

Руководство по установке

  1. В файле pom.xml проекта MVC добавьте зависимость от компонента adapter-common, после добавления зависимости от этого компонента проект получит возможность динамически загружать сторонние компоненты, динамически вводить конфигурацию в соответствии с префиксом конфигурации и условно вводить в контейнер Spring.
<dependency>
    <groupId>com.opages.mvc.adapter</groupId>
    <artifactId>adapter-common</artifactId>
    <version>1.0.0</version>
</dependency>
  1. В файле applicationContext.xml проекта MVC настройте зависимость от входного класса MVCAutoConfiguration.java, после того как компонент adapter-common будет добавлен в качестве зависимости, вам нужно передать входной класс Spring для управления, чтобы компонент мог реализовать все свои функции (то есть @SpringBootApplication).
<bean class="com.opages.mvc.adapter.common.autoconfigure.MVCAutoConfiguration" />
  1. В файле pom.xml проекта MVC добавьте зависимость от компонента adapter-nacos (возьмём nacos в качестве примера для регистрации центра), чтобы реализовать регистрацию и обнаружение служб.
<dependency>
    <groupId>com.opages.mvc.adapter</groupId>
    <artifactId>adapter-nacos</artifactId>
    <version>1.0.0</version>
</dependency>
  1. Добавьте конфигурацию регистрации и обнаружения центра в файл конфигурации проекта MVC.
#激活nacos注册中心
spring.mvc.nacos.enable=true
#MVC服务定义为一个服务,设置服务名
``` **spring.mvc.nacos.discovery.serviceName=mvc-example**

# nacos 注册中心地址
**spring.mvc.nacos.discovery.serverAddr=http://127.0.0.1:8848**

# nacos 服务版本号
**spring.mvc.nacos.discovery.metadata[version]=1.0**

# nacos 服务权重
**spring.mvc.nacos.discovery.metadata[weight]=10**
  1. MVC 项目实现服务间调用,依赖 adapter-openfeign
<dependency>
    <groupId>com.opages.mvc.adapter</groupId>
    <artifactId>adapter-openfeign</artifactId>
    <version>1.0.0</version>
</dependency>
  1. MVC 项目配置文件中增加 openfeign 激活
# 激活 feign 功能,默认 false,不开启则不能使用 openfeign
**spring.mvc.openfeign.enable=true**
# SpringMVC 中启动 FeignClient 包的扫描路径地址
**spring.mvc.openfeign.scan=com.opages.mvc.**.**.api**

Разработка

  1. Создать API 服务工程, определить сервис API 接口 (обычно можно создать отдельный API 工程, таким образом, если другие сервисы вызывают сервис, можно использовать этот API сервис для реализации возможности вызова других сервисов, если уже существуют сервисы, то просто нужно сопоставить оригинальный URL с URI API, обратите внимание на согласованность параметров, рекомендуется использовать DTO).
@FeignClient(name="mvc-example")
@RequestMapping("/mvc/example")
public interface MvcExampleApi {
    @PostMapping("/get")
    @ResponseBody
    public MvcExampleDto getExample(@RequestParam("id") Integer id);

    @PostMapping(value="/save")
    public void save(MvcExampleDto exampleDto);
}
  1. Создать сервис провайдера проекта, реализовать API интерфейс и реализовать бизнес-логику.
@RestController
public class MvcExampleController implements MvcExampleApi {
    @Override
    public MvcExampleDto getExample(@RequestParam("id") Integer id) {
        MvcExampleDto dto = new MvcExampleDto();
        dto.setId(id);
        dto.setUsername("xiaomin");
        dto.setPassword("123456");
        return dto;
    }

    @Override
    public void save(@RequestBody MvcExampleDto demoDto) {
        System.err.println("MVC Example 保存 -->" + demoDto.toString());
    }
}

Техническое описание

  1. Spring 整体流程

Когда вы изучаете Spring, часто говорят о IOC и AOP, чтобы понять, что такое IOC и AOP, а затем говорят, что Bean управляется Spring. Когда мы обсуждаем, как Spring это делает, многие люди все еще сводят его к использованию отражения, Java динамического прокси или cglib. Если мы изменим способ понимания: IOC и AOP - это как они были разработаны? Как бы вы это объяснили?

Ответ на вышеуказанный вопрос перед просмотром ApplicationContext потока, поскольку этот проект использует традиционный Spring MVC, поэтому сначала посмотрите на загрузку XML контекста ClassPathXmlApplicationContext (Spring версия: 4.3.29).

Spring поток анализа каждый раз хочет упростить поток Spring, чтобы увидеть общую картину, но внутренняя конструкция взаимосвязана, и, начиная с определенного блока в качестве отправной точки, всегда будет не хватать чего-то, поэтому сначала объясните общую ситуацию с точки зрения бизнес-диаграммы, а затем отметьте ключевые процессы (другие не являются незначительными, просто разные точки внимания), чем больше вы анализируете исходный код Spring, тем больше вы чувствуете себя слабым цыпленком, так что, если у вас есть какие-либо ошибки, пожалуйста, оставьте сообщение, чтобы дать обратную связь. Ниже приведена ключевая диаграмма процесса:

Из приведенного выше процесса можно видеть, что просто говорить о технических принципах IOC и AOP недостаточно, чтобы объяснить, как реализовать проблему, и проблема реализации должна быть рассмотрена с точки зрения дизайна и общей архитектуры, то есть так называемого комплексного решения. С точки зрения определения Bean (абстрактный BeanDefinition), построения Bean (построение отражения и FactoryBean), создания Bean (инстанцирование и инициализация), а также основного дизайна расширения точки: постпроцессор пронизывает весь процесс. IOC и AOP связаны с постпроцессором. Чтобы Spring выполнял работу, необходимо выполнить два условия: ①. Bean управляется spring, ②. Атрибуты инъекции (значения или объекты) управляются spring, и основной операцией для достижения этой цели является постпроцессор. Из упрощенной диаграммы процесса выше видно, что Spring широко использует постпроцессор, который можно разделить на две большие категории:

(1). BeanFactoryPostProcessor: вмешательство в создание процесса BeanFactory, может прочитать конфигурацию метаданных перед контейнером экземпляра любого другого bean, изменить определение атрибута bean в соответствии с потребностями, необходимо обратить внимание на подынтерфейс BeanDefinitionRegistryPostProcessor, метод postProcessBeanDefinitionRegistry этого интерфейса определяется как родительский класс, главным образом для динамической регистрации аннотаций, соответствующих spring (@Component, @Service, @Controller и т.д.), генерирует DebanDefinition в контейнер.

(2). BeanPostProcessor: вмешивается в процесс создания Bean, присваивает значения свойствам при создании экземпляра Bean, например: Aware инъекция, @Autowired аннотация присваивает значение свойствам, общая проверка свойств, инициализация и уничтожение методов (@PostConstruct, @PreDestroy) вызов, реализация нижнего уровня динамического агента.

Дело должно быть сделано в общем сознании, после краткого объяснения выше, теперь мы можем поговорить о дизайне IOC и AOP. Во-первых, это этап подготовки, Spring заранее подготовил среду переменных, синтаксический анализатор, конвертер и т. д., которые применяются при чтении файлов и анализе файлов, и вызывает, когда это необходимо, BeanFactoryPostProcessor для предварительной обработки, сначала выполняет подынтерфейс BeanDefinitionRegistryPostProcessor для анализа Bean с использованием аннотации, наконец, анализирует ее в BeanDefinition, а затем выполняет интерфейс BeanFactoryPostProcessor, изменяет некоторые свойства Bean по умолчанию, внутренний интерфейс реализации:

- ConfigurationClassPostProcessor:конфигурация класса постпроцессора, анализ конфигурации класса с добавлением @Configuration, анализ @ComponentScan, @ComponentScans аннотированный пакет сканирования, анализ @Import, @Bean аннотированных. - PropertyPlaceholderConfigurer:в файле конфигурации XML добавить внешний файл свойств, ${key} заменить указанное значение в файле свойств. - PropertyOverrideConfigurer:разрешить переопределение любых свойств (beanName.propertyName=value) в определении bean, которое мы хотим обработать в Spring контейнере. - CustomEditorConfigurer:тип преобразователя, в зависимости от типа объекта, получить соответствующий PropertyEditor для конкретного преобразования типа.

После завершения обработки свойств Bean, согласно BeanPostProcessor (подынтерфейс InstantiationAwareBeanPostProcessor) постпроцессору, перед и после инстанцирования, инициализации до и после выполнения динамического расширения (введение свойств, создание прокси, выполнение метода инициализации, введение метода уничтожения):

- CommonAnnotationBeanPostProcessor:переписать postProcessPropertyValues, ввести @Resource - AutowiredAnnotationBeanPostProcessor: переписать postProcessPropertyValues, ввести @Autowire - PersistenceAnnotationBeanPostProcessor:используется для введения соответствующего ресурса JPA АбстрактАвтоПроксиКриэйтор: инициализация перед (постПроцессБефореИнстантиатион) возвращает указанный прокси-объект динамического прокси (не часто используется), инициализация после (постПроцессАфтерИнициализатион) возвращает обычный динамический прокси (Спринг АОП).

— КоммонАннотатионБинПостПроцессор: собирает @ПостКонструкт, @ПреДестрой (методы инициализации и уничтожения), внедряет классы с аннотацией @Ресурс. — ИмпортАварБианПостПроцессор: внедряет AnnotationMetadata подклассов ImportAware.

После вышеуказанной обработки создание Бина успешно завершается, и он помещается в кэш. В следующий раз он будет взят непосредственно из кэша.

— АОП реализуется через подклассы BeanPostProcessor.

  1. Предварительное условие: в классе конфигурации есть аннотация @ЭнэблАспектДжейАвтоПрокси. Эта аннотация имеет атрибут @Импорт (класс АспектДжейАвтоПроксиРегистрэр.класс), который импортирует класс АспектДжейАвтоПроксиРегистрэр, который наследуется от ИмпортБинДефинитионРегистрэр и, следовательно, может быть настроен для внедрения BeanDefinetion -> АннотатионАварАспектДжейАвтоПроксиКриэйтор. Класс, который внедряется, является подклассом постпроцессора AbstractAutoProxyCreator. Этот класс также наследует от BeanFactoryАвар, потому что при установке BeanFactory создаются advisor фабрика классов (РефлективАспектДжейАдвайзорФактори) и конструктор классов (БинФабрикАспектДжейЭдвайзорсБилдерАдаптер) для создания объектов Aspect.
  2. После того как Бин был создан, вызывается обратный вызов инициализации перед (постПроцессБефореИнстантиатион), чтобы определить, можно ли его проксировать (есть ли @Аспект, реализует ли Advice, Pointcut, Advisor, AopИнфраструктураБин, если да, то не проксируется). Во время определения выполняется поиск класса с аннотацией @Аспект. Затем генерируется объект Advisor (метод ReflectiveAspectJAdvisorFactory.гетЭдвайзорс() создаёт его на основе существования pointCut). Если существует pointCut, выражение pointCut expressionPointcut и ReflectiveAspectJAdvisorFactory будут упакованы в объект advisor (ИнстантятионМоделАварПойнткутЭдвайзорИмпл). Конструктор ИнстантятионМоделАварПойнткутЭдвайзорИмпл вызовет конструктор уведомления (соответствующие аннотации генерируют Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class). Через конструктор уведомлений метод расширения уведомления будет добавлен, а выражение среза будет передано в уведомление. Затем Advisor сохраняется в advisedBeans (если нет пользовательского целевого класса, процесс завершается). Логика создания advisor находится в расширенном интерфейсе в postProcessBeforeInstantiation, выполняется до создания экземпляра. Если есть пользовательский TargetSource, указывающий класс, то прокси-класс создаётся напрямую и сразу же выполняется метод инициализации после (постПроцессАфтерИнстантиатион). Такая ситуация используется нечасто, обычно прокси-классы создаются после инициализации (последний метод расширения IOC).
  3. После инициализации Бина вызывается метод AnnotationAwareAspectJAutoProxyCreator.постПроцессАфтерИнстантиатион. Он вызывает getAdvicesAndAdvisorsForBean() для получения подходящего advisor. Этот метод в конечном итоге вызывает findEligibleAdvisors(), а затем фильтрует по правилам AopUtils (перебирает все методы класса, который должен быть проксирован, сравнивает их с выражениями срезов, если метод совпадает, класс будет проксирован. Если проксируемый класс является интерфейсом или типом Proxy, используется тип jdk, в противном случае используется cglib. Springboot 1.x и 2.x различаются). Наконец, возвращается проксированный класс.

Вкратце: при активации аннотации AnnotationAwareAspectJAutoProxyCreator создаётся AnnotationAwareAspectJAutoProxyCreator, который наследует BeanPostProcessor и реализует BeanFactoryAware, поэтому также создаётся Advisor фабрика. При создании Advisor объекта с помощью Advisor фабрики после создания Бина также создаётся класс расширения уведомлений. После инициализации Бина в соответствии с правилами AopUtils сопоставляется выражение pointCup для создания динамического JDK или Cglib прокси целевого класса и возврата его в контейнер.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/yoin-mvc-adapter-cloud.git
git@api.gitlife.ru:oschina-mirror/yoin-mvc-adapter-cloud.git
oschina-mirror
yoin-mvc-adapter-cloud
yoin-mvc-adapter-cloud
master