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

OSCHINA-MIRROR/wkgcass-Pure.IoC

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Pure.IoCEN.md 19 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 27.02.2025 16:03 225802b

Нажмите здесь (cassite) или здесь (git@osc) для получения русскоязычной версии документации.

Pure.IoC

Pure.IoC — это легковесный фреймворк внедрения зависимостей на основе типов и аннотаций.

основан на JDK 1.8
Рекомендуется использовать вместе с Spring

<dependency>
  <groupId>net.cassite</groupId>
  <artifactId>pure.ioc</artifactId>
  <version>0.3.2</version>
</dependency>

Философия

Замена сложной конфигурации на логическую зависимость.

Основные возможности

  • IOC
  • AOP

Концепция дизайна

Обычно мы используем Spring для управления IOC. Однако Spring основывается на bean, что требует отображения класса в bean и последующего описания зависимостей этих bean.

На самом деле, зависимости могут быть определены только по типу.
Пример:

class A{
    ...
    public void setB(B b){ this.b = b; }
}

class B{}

Очевидно, что A зависит от B. A требует экземпляр B для внедрения через метод setB. Это естественная логическая связь.

Зависимости типа устанавливаются при программировании. Поэтому было бы здорово, если бы какие-то инструменты/фреймворки помогли бы работать с этой очевидной зависимостью.
Поэтому я создал Pure.IoC

Архитектура фреймворка

Расширяемость

Мне потребовалось много времени для того, чтобы спроектировать Pure.IoC.
В качестве примера рассмотрим следующую сложную ситуацию (хотя она все еще не очень сложная):

@Singleton
@Wire
class Complex{
    private ......
    
    public Complex(){ ... }
    @Default public Complex(AnotherClass obj){ ... }
    
    public void setA(A a){ ... }
    public void setB(B b){ ... }    
    public void setInterface(Interf1 interf){ ... }
    public void setInterface(@Use(clazz=Impl2.class)Interf2 interf){ ... }
}

@Default(clazz=Impl1.class) interface Interf1{ ... }

Аннотации означают:

  • @Singleton Complex является синглтоном
  • @Wire Выполняет соединение при автоматическом соединении класса
  • @Default Выбирает конструктор по умолчанию (используется на конструкторах), определяет реализацию класса (используется на интерфейсах)
  • @Use Определяет, какой класс использовать

Аннотации должны иметь возможность бесконечного расширения, но при этом система не должна становиться более сложной.
В конце концов я спроектировал следующий паттерн:

AnnotationHandler + HandlerChain

AnnotationHandlers разделены на четыре типа:

  • SetterAnnotationHandler Используется для вызова сеттеров, принимает во внимание аннотации на сеттерах/соответствующих полях/параметрах.
  • ParamAnnotationHandler Используется для получения экземпляров с указанным типом, принимает во внимание аннотации на параметрах.
  • ConstructorFilter Используется для выбора конструкторов, принимает во внимание аннотации на конструкторах.
  • TypeAnnotationHandler Используется для выбора типа, принимает во внимание аннотации на типах.

Хэндлеры регистрируются в IOCController, и выполняют операции обработки в порядке регистрации. Реализация хэндлеров выглядит как AOP, обычно они вызывают chain.next().handle(...), выполняя соответствующие действия, учитывая результаты или исключения следующего хэндлера.

Дополнительная информация доступна в документации хэндлеров.

Как результат, расширение становится очень удобным.

Циклические зависимости

Хотя циклические зависимости обычно не встречаются, иногда они возникают. A->B->C->A
Средний один из A, B, C должен быть синглтоном, иначе процесс создания будет продолжаться.

Spring требует, чтобы конструкторы не имели циклических зависимостей, иначе процесс создания не завершится.

Однако Pure.IoC решает эту проблему умело.

  • Все внедрения производятся при создании. Создание не завершается до полного выполнения всех внедрений.
  • Для синглтонов они передают свои ссылки в IOCController, чтобы система знала, что синглтон уже существует.
  • Создание завершается только после завершения всех внедрений, поэтому не стоит беспокоиться о том, что объекты могут не быть полностью созданы.

В результате, внедрения могут успешно происходить даже при наличии циклических зависимостей (в действительности, все зависимости являются зависимостями конструктора в рамках этого фреймворка).

Гибкость

Pure.IoC спроектирован так, чтобы внедрять зависимости при создании, поэтому нет необходимости в других модулях при использовании его в других фреймворках. Хорошая идея использовать этот фреймворк вместе с Spring. Даже можно делать внедрение некоторых сеттеров с помощью Pure.IoC, а остальные — с помощью Spring.

Также он не требует никакой конфигурации при использовании некоторых фреймворков, таких как Struts2. Внедрения находятся внутри класса, поэтому нет необходимости менять фабрику объектов Struts2. (объект сам по себе является фабрикой)

Рекомендованный способ использования этого фреймворка:

extends AutoWire

Но в некоторых случаях класс уже расширяет другой класс, есть два запасных варианта:

@Wire class A { ... }

Любой класс с аннотацией @Wire будет внедрен при прохождении Pure.IoC.

Вы можете использовать:

AutoWire.get(A.class)

для получения экземпляров.

class A {
    public A(){
        AutoWire.wire(this);
    }
}

Передайте свое представление фреймворку при создании.

На самом деле все входы будут вызывать AutoWire.wire(Object)

Как использовать?

  • Во-первых, используйте три вышеупомянутых метода для активации внедрений.

  • Затем вызовите следующий метод в начале вашего приложения.

      IOCController.autoRegister();

    или зарегистрируйте каждый хэндлер вручную. Например,

        register(new DefaultConstructorFilter());

    если вы пишете JavaEE, вы можете создать Listener для выполнения этой работы.

  • Наконец используйте

      IOCController.closeRegistering();

    чтобы закрыть регистрацию хэндлеров.
    Этот шаг является необязательным, только для гарантии, что список хэндлеров не будет изменен.

Регистрация без хэндлеров и начало соединения приведут к вызову autoRegister и closeRegistering.

По умолчанию поведение

Поведение по умолчанию без представленных аннотаций:

Когда внедряется сеттер, получает тип параметра и запрашивает экземпляр у IOCController. Затем вызывает сеттер.

Когда пытаются получить экземпляры, получает единственный конструктор, или конструктор без параметров.
Если конструктор имеет параметры, получает экземпляры соответствующих типов.
Наконец, выполняет создание.

Расширенные Аннотации

Сеттер* Use(clazz, constant, variable)

**clazz** использует заданный тип как аргумент. Затем выполняется проверка типа.  
**constant** представляет константы, зарегистрированные в IOCController.  
**variable** представляет переменные, зарегистрированные в IOCController.
  • Force(value)
    Преобразует строковое значение в правильный тип. Force поддерживает примитивные типы и строки.
  • Ignore
    Игнорирует сеттер
  • Extend(handler, args)
    Получает объекты из других фабрик объектов
    handler ExtendingHandler, имя хэндлера, который описывает, как получать объект из фабрики объектов
    args аргументы для заполнения хэндлера
  • Session(value)
    аргумент будет делиться в одной и той же сессии
    value псевдоним деления

Тип

  • Wire
    указывает, что класс требует внедрения зависимостей.
  • Singleton
    указывает, что класс является синглтоном
  • Default(clazz)
    Обычно используется на интерфейсах или абстрактных классах
    Целевой объект будет переопределен при выполнении проверки типа.

Конструктор

  • Default()
    указывает конструктор для использования при выборе конструктора, если метод выбора неоднозначен

Параметр

  • Use(clazz, constant, variable)
    clazz использует заданный тип как аргумент. Затем выполняется проверка типа.
    constant представляет константы, зарегистрированные в IOCController.
    variable представляет переменные, зарегистрированные в IOCController.
  • Force(value)
    Преобразует строковое значение в правильный тип. Force поддерживает примитивные типы и строки.
  • Extend(handler, args)
    Получает объекты из других фабрик объектов
    handler ExtendingHandler, имя хэндлера, который описывает, как получать объект из фабрики объектов
    args аргументы для заполнения хэндлера
  • Session(value)
    аргумент будет делиться в одной и той же сессии
    value псевдоним деления

Также параметры предоставляют внедрение примитивных типов.
Если внедрения не найдены, он проверяет примитивные типы и массивы, и внедряет начальными значениями (0, false, массив[length= Yöntemleri])

Другое

Сессия

Сессия существует в течение периода инициализации соединения до завершения соединения. Почти все методы передают сессию как аргумент. Пример:
A зависит от B, B зависит от C и D. Также, A и C расширяют AutoWire (что неявно вызывает AutoWire.wire(o)), B и D используют аннотацию Wire
Тогда, работа соединения ABD будет делиться одной сессией, а работа соединения C принадлежит другой.

Утилиты

Pure.IoC предоставляет класс утилит Utils, содержащий некоторые обычные операции, с некоторыми методами в IOCController. Если расширение IOCController неудобно, вы можете использовать методы в Utils для вызова защищённых методов в IOCController.

ExtendingHandler

Цель дизайна этого — упрощение работы получения объектов из других фабрик объектов. Но использование не ограничивается этим.
Фактически, это может рассматриваться как упрощение расширения.
Это используется для выполнения обработки типов, сеттеров и параметров, но принимаемые аргументы могут быть только массивами строк.

SessionAware

Для тех классов, которые реализуют SessionAware, или классов с методом setScope(Scope s) и помеченных аннотацией @Wire, будет вызван текущий диапазон.

AOP

Поддержка AOP была добавлена с версии 0.1.1

введите аннотацию

@AOP({Weaver.class,...})

в ваш класс с интерфейсами, чтобы получить поддержку AOP

Когда класс соединяется с Pure.IoC или прямо получает экземпляр с помощью

AOPController.weave(() -> Instance of the class, InstanceClass.class)

будет получен прокси-объект.

Как использовать?

Создайте свой Weaver

class YourWeaver implements Weaver{
    @Override
    protected void doBefore(AOPPoint point) {
        ...
    }

    @Override
    protected void doAfter(AOPPoint point) {
        ...
    }

    @Override
    protected void doException(AOPPoint point) throws Throwable {
        ...
    }
}

до, после, исключение означают Before, AfterReturn, AfterThrowing. Просто расширяет Weaver означает Around.

BeforeWeaver, AfterWeaver, ExceptionWeaver также предоставлены, расширяет их, если вам нужен только конкретный тип точки разреза.

Также очень удобно, если вам требуется Introduction. Единственное, что вам нужно сделать, это позволить вашему классу Weaver реализовать интерфейсы, которые вы хотите ввести.

Weaving

используйте

@AOP({Weaver1.class, Weaver2.class, ...})

для введения.
Если используется cglib, вы можете установить useCglib=true

@AOP(value={Weaver1.class, Weaver2.class, ...}, useCglib=true)

процесс AOP следует следующим шагам.

  • Получает экземпляры Weaver с помощью AutoWire.get(Class)
  • Устанавливает переменную для хранения текущего индекса массива Weaver.
  • Выполняет 'before' от первого до последнего.
  • --Если returnValue был установлен, просто переходите к шагу 'after'.
  • Вызывает метод
  • --Если произошло исключение, выполняет 'exception' от последнего до первого.
  • Выполняет 'after' от хранимого индекса до первого.

AOPPoint

Этот класс содержит следующие открытые поля/методы

  • target таргет объект
  • method текущий метод
  • args аргументы (может быть модифицирован непосредственно)
  • returnValue() получает возвращаемое значение
  • returnValue(Object) устанавливает возвращаемое значение
  • exception() получает текущее исключение
  • exceptionHandled() маркирует, что текущее исключение было обработано

TargetAware

Для тех вейверов, которые реализуют TargetAware, метод targetAware(.) будет вызван после получения экземпляра вейвера с использованием прокси-таргета в качестве аргумента.

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

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

1
https://api.gitlife.ru/oschina-mirror/wkgcass-Pure.IoC.git
git@api.gitlife.ru:oschina-mirror/wkgcass-Pure.IoC.git
oschina-mirror
wkgcass-Pure.IoC
wkgcass-Pure.IoC
master