Практическое применение динамических прокси

Java Python
Практическое применение динамических прокси

Оригинальная ссылка

предисловие

недавно использованныйPythonизSQLAlchemyбиблиотечное время (аналогичноHibernateизORMкаркас), найти егоEventsСобытия в порядке.

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

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

Согласно моему предыдущему использованиюMybatisЯ, кажется, не обращал особого внимания на эту функцию, я проверил ее и обнаружил, чтоHibernateОн поддерживается, но я им мало пользуюсь, так что мне все равно.

Постепенно уходите от темы. . .

Основная причина, по которой я говорю это, заключается в том, что я намерен написать для предыдущегоcicada(Легкая структура http) плюс пакет операций с базой данных также выполняет аналогичные функции.

Пример

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

Первая версия еще относительно сырая, но функции все есть.

Шаг 1: Вам необходимо реализовать интерфейс инициализации, который будет выполняться при инициализации приложения.


Далее нам нужно определитьModel:

@Data
@OriginName("user")
@ToString
public class User extends Model {
    @PrimaryId
    private Integer id ;
    private String name ;
    private String password ;

    @FieldName(value = "city_id")
    private Integer cityId ;

    private String description ;

}

Соответствующая структура таблицы выглядит следующим образом:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  `description` varchar(100) DEFAULT NULL,
  `roleId` int(11) DEFAULT NULL COMMENT '角色ID',
  `city_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
)

Когда вам нужно запросить данные:

Вы можете получить доступ к базе данных таким образом.


Когда данные необходимо обновить:

в инициализацииDBHandleПри указании callback-интерфейса (то есть здесьUserUpdateListener), вы можете получить измененный объект данных при изменении данных.

@Slf4j
public class UserUpdateListener implements DataChangeListener {
    @Override
    public void listener(Object obj) {
        log.info("user update data={}", obj.toString());
    }
}

В то же время мы можем видеть результат обратного вызова при изменении данных в консоли:

Таким образом реализуются функции, упомянутые в начале статьи, и может быть реализована некоторая бизнес-логика, которую необходимо выполнить после изменения данных.

выполнить

Сосредоточимся на процессе реализации этой функции, собственно, генерируяDBHandle(Интерфейс для добавления, удаления и модификации базы данных) instanceAPIНекоторые подсказки можно увидеть.

DBHandle handle = (DBHandle) new HandleProxy(DBHandle.class).getInstance(new UserSaveListener());

DBHandelХотя это интерфейс, он реализован не с использованием класса реализации, а сгенерирован прокси-сервером.

Итак, каковы преимущества создания через прокси, а не непосредственного создания экземпляра класса реализации?

Например, скажем, сейчас вы хотите купить новый телефон.

Первый способ - купить стандартный мобильный телефон прямо в официальном флагманском магазине, там только один мобильный телефон без доп.

Конечно, вы также можете покупать пакеты вместе с пакетами у некоторых сторонних реселлеров, таких как套餐一Больше, чем стандарт保护壳、贴膜дополнительные свойства, такие как .

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

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


Давайте посмотрим, как генерируется этот прокси-класс:

основное использованиеJDKавтономныйAPIРеализовано, конкретные параметры могут напрямую ссылаться на официальную документацию:docs.Oracle.com/java-color/8/do…

Во всяком случае, это создаетDBHandlerПрокси-объект интерфейса, а реальный прокси-процесс находится вInvocationHandler#invoke()Реализовано в функции:

Реализация здесь тоже очень простая: после реализации бизнес-логики прокси-объекта происходит обратный вызов переданного нами интерфейса события, а параметром является текущая база данных.Modelобъект сущности.

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

Суммировать

Выше приведена вся реализация динамического прокси.ORMВесь процесс механизма мониторинга, на самом деле, видно, что он не выглядит таким высоким, как его название, и, конечно, сама реализация относительно проста.

В то же время существует более одной реализации, например:

  • cglib
  • javassist
  • ASM

etc..

Их конкретная реализация и преимущества и недостатки в этой статье не рассматриваются, если вам интересно, я реализую эту функцию этими способами.

При этом применение динамических прокси этим не ограничивается, например:

  • RPCНеосознанные удаленные вызовы в .
  • SpringсерединаAOP, перехватчики и т.д.

Будет продолжать улучшать это в будущемORMБиблиотека или даже автономный инструмент для небольшой базы данных — неплохая идея.

См. соответствующий исходный код здесь:GitHub.com/вместе ОС/…

Ваши лайки и репост - лучшая поддержка для меня

公众号名片底部.jpg