Я почти уверен, что Finalize по-прежнему является плохой новостью для более поздних JVM - есть ли альтернатива?

StackOverflow https://stackoverflow.com/questions/5359367

  •  27-10-2019
  •  | 
  •  

Вопрос

Я хотел бы реализовать систему в стиле ORM, которая могла бы сохранять обновления POJO, когда они больше не доступны вызывающему абоненту.

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

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

Есть ли другой путь, о котором я не думаю, кроме обязательного «Просто позвоните вызывающему абоненту .save(), когда он закончит»?

Это было полезно?

Решение

Ты просто пытаешься избежать необходимости звонить save() на каждом POJO, который вы изменяете?

Это можно сделать надежно, используя объект сеанса персистентности, например:

  1. Откройте новый объект сеанса.
  2. Загружайте объекты через объект сеанса.Объект сеанса поддерживает ссылки на все загружаемые им объекты.
  3. Внесите любые изменения в загруженные объекты.Нет необходимости вызывать метод сохранения для обновленных объектов.
  4. Закройте объект сеанса.Сеанс сохраняет все свои объекты.Возможно, было бы даже достаточно причудливо сохранить копию чистых загруженных данных, сравнить все ее объекты с чистыми данными и сохранить только те, которые были изменены.

А если вы не хотите передавать объекты сеанса через свой код, вы можете пойти еще дальше с помощью шаблона «Единица работы», связав объект сеанса с текущим потоком:

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

Это устраняет несколько проблем с решением, основанным на достижимости:

  • Вы не полагаетесь на недетерминированные сборки мусора, между запусками которых может пройти много времени или которые могут вообще не выполняться.
  • Все объекты, измененные за одну операцию, сохраняются вместе.Если вы полагаетесь на достижимость, разные объекты, измененные в ходе одной и той же операции, могут стать недоступными в разное время, а это означает, что ваши изменения могут быть сохранены в базе данных по частям.
  • Откат намного проще — просто дайте объекту сеанса методrollback().При использовании решения достижимости вам нужно будет не забыть вызвать функциюrollback() для каждого измененного POJO, если операция не удалась, что на самом деле совпадает с вашей исходной проблемой.

Возможно, см. http://nhibernate.info/doc/patternsandpractices/nhibernate-and-the-unit-of-work-pattern.html или исследуйте шаблон «Единица работы» и подражайте некоторым из этих идей.

Другие советы

Используйте шаблон наблюдателя. Сделайте построение EranceManager и некоторые разрушительные. Idestroyable - это интерфейс, который используется для наблюдателей, он содержит метод Public void Destress (). ErancanceManager является предметом ObserverPattern. Возможно, используйте здесь Singleton, чтобы убедиться, что у вас есть только один объект FlueranceManager в вашем приложении.

Используйте набор Internaly внутри ElaranceManager (не список, чтобы убедиться, что объекты можно добавить один раз)

Поддержите метод AddeStroyable (Sidestroyable Destoryable) (и, возможно, снятый эгровой).

Во время выполнения классы, для которых вам нужна эмуляция деструктора, может зарегистрировать себя в ClearenceManager. ClearenceManager.getInstance (). AddEdestroyable (это);

У ElaranceManager есть метод доклеарного (), который следует просто вызвать в конце основного метода. Это итераты бросают частный набор и вызовы Destroy () на каждый обозначительный объект.

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

Возможно, если вы не хотите звонить DoceLance () в своем основном методе, который вы можете использовать здесь, но только здесь, настоящий деструктор Finalize (). Поскольку в Clearencemanager есть ссылки на необходимые объекты, они не будут уничтожены в первую очередь. Но, может быть, MHH, если есть перекрестные ссылки .... лучше не использовать infintize, используйте документ () и повеселитесь с ним :)

Я думаю, что вы лаете здесь не то дерево.

Все финализаторы Java и эталонные механизмы, основанные на достижении досягаемости, зависят от сборщика мусора, чтобы определить, достижимы ли соответствующие объекты. Поэтому, если вы используете какие -либо справочные механизмы для какого -то завершения, вы сталкиваетесь с теми же проблемами, которые делают finalize плохая идея.

Технически возможно реализовать свои собственные механизмы для достижения досягаемости; Например, реализуя свой собственный подсчет ссылок, специфичный для приложения. Тем не менее, это, вероятно, будет дорого, хрупким и сделает ваш код ужасно. (Ссылка на Java, вероятно, будет более сложным и хрупким, чем в C ++, потому что вы не можете перегружать операторов назначения ссылки, чтобы убедиться, что счетное количество ссылок регулируется прозрачно. Таким образом, каждое ссылочное назначение должно быть завершено в вызов метода.) Таким образом Я бы сказал, что выполнение собственного анализа достижимости - это плохая идея.

Итак, чтобы быть практичным, вам нужно либо:

  • переосмыслить ваш дизайн, чтобы не делать что -то в зависимости от достижения, или
  • Живите с последствиями использования завершения.

Первый вариант явно лучший, ИМО.

Может быть, вы можете подкласс PhantomReference и хранить в нем необходимые данные для окончательных действий.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top