Что является кратким примером объявлений между типами в AspectJ, который демонстрирует полезность этого подхода?
Сначала я подумал об использовании ITD для определения private static final Logger logger = ...
для некоторых не связанных между собой случаев, но это не выглядит как очевидное улучшение, чтобы использовать это в качестве демонстрационного примера.
Есть ли какой-нибудь стандартный / предлагаемый пример использования ITD, который люди должны использовать в учебных целях?
3 ответа
Я хотел бы добавить еще один пример к ответу Адама.
Использование аспектов - это способ улучшить модульность вашего программного обеспечения, а также ООП, за исключением того, что ООП применяется "вертикально", а АОП применяется "горизонтально".
Таким образом, хотя совет может использоваться для изменения "по горизонтали" поведения всех методов, отвечающих некоторым критериям, для некоторого кода в совете потребуются также некоторые данные, и ITD позволяет добавлять эти поля "горизонтально", в то же время одновременно в одном блоке компиляции (аспект) связаны данные и код.
Поскольку вы добавляете данные через поля ITD, вы, вероятно, также захотите предложить какой-нибудь метод для управления этими полями, например, метод set /getter.
Я пытался перефразировать это несколько раз, надеюсь, это легко понять.
В качестве примера предположим, что у вас есть программа графического редактирования, где пользователь может создавать, удалять и отображать несколько фигур (довольно канонично, да?:D).
У фигур много данных, например, у них есть цвет, координаты и т. Д., Которые правильно принадлежат самому классу. Однако, так как это приложение Web 3.0, вы хотите, чтобы пользователи могли взаимодействовать на одном чертеже, а это означает, что каждая фигура должна знать, когда она изменяется, если она была передана другим пользователям, что форма изменена, не важно заблокирован каким-либо пользователем, который фактически перетаскивает его и т. д.
Вы можете сделать это в простой ООП, реализуя соответствующие части в Shape или в любом другом своем корневом классе, но вы будете загрязнять все ваши сеттеры вызовами типа "this.setDirty(true)" или подобными вещами.
Вместо этого вы решаете пойти АОП и реализовать его в аспекте. В этом случае вы можете легко добавить совет после всех установщиков, но вам также нужно будет сохранить "грязный" логический параметр или даже список свойств, которые изменились, если вы хотите оптимизировать сетевой протокол, отправляя только дельты изменений.
Вы могли бы реализовать это как
public aspect ShapesAreDirtyThings {
private boolean Shape.dirty;
after(Shape s) : execution(* Shape+.set*(..)) {
s.dirty = true;
// Set some other global field, start a thread to communicate
// to other users about the change, whatever ..
}
public boolean Shape.isDirty() {
return s.dirty;
}
public boolean Shape.findDirtyChildren() { // whatever
}
Вы ничего не можете сделать с обычным AOP, это просто вопрос инкапсуляции в единую рекомендацию модуля компиляции, данных, необходимых для этой рекомендации, и методов, которые в конечном итоге будут работать с этими данными.
Java не поддерживает множественное наследование или миксин. Но с помощью ITD вы можете сделать Scala как Traits или Ruby как Mixins.
Вот пример использования JPA и Spring Configurable:
Интерфейс:
package com.evocatus.aop;
public interface DomainNotify {
public void postPersist();
public void postUpdate();
public void postRemove();
}
AspectJ ITD:
package com.evocatus.aop;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
import javax.persistence.PostUpdate;
import javax.persistence.Transient;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.springframework.beans.factory.annotation.Autowired;
import com.evocatus.service.DomainNotifyService;
privileged aspect DomainNotifyAdvice {
@JsonIgnore
@Transient
@Autowired
transient DomainNotifyService DomainNotify.domainNotifyService;
@PostPersist
public void DomainNotify.postPersist() {
this.domainNotifyService.publishSave(this);
}
@PostUpdate
public void DomainNotify.postUpdate() {
this.domainNotifyService.publishUpdate(this);
}
@PostRemove
public void DomainNotify.postRemove() {
this.domainNotifyService.publishRemove(this);
}
}
Теперь любой класс, который реализует DomainNotify, получит встроенные методы ITD.
@Entity
@Configurable
public class MyJPAObject implements DomainNotify {
}
Посмотрите на Spring ROO. Это быстрый разработчик. env используя Spring. Я вижу это как Ruby on Rails, но в Java с Spring;-)
Он много использует ITD для генерации getter, setter, toString и т.д... на основе атрибутов, которые вы определяете при создании вашего Class.