I first thought about using ITDs to define the private static final Logger logger = ...
for some unrelated cases, but it doesn't look enough like an obvious improvement to use that as a demonstration example.
Is there some standard/suggested example of ITD usage, which people should use for teaching purposes?
I'd like to add another example to Adam's answer.
Using aspects is a way to improve modularization of your software, as well as OOP is, except that OOP is applied "vertically", while AOP is applied "horizontally".
So, while advice can be used to modify "horizontally" the behavior of all methods responding to some criteria, aften code in advice will need also some data, and ITD makes it possible to add that fields "horizontally" while at the same time contain in a single compilation unit (the aspect) related data and code.
Since you are adding data via ITD fields, you'll probably also want to offer some method to manipulate those fields, like a setter/getter.
I tried to rephrase it a few times, I hope it's easy to understand.
To give you an example, suppose you have a graphical editing program, where the user can create, delete and display a number of Shapes (pretty canonical eh? :D ).
Shapes have a lot of data, for example they have a color, coordinates etc.. which correctly belong to the class itself. However, since this is a web 3.0 application, you want users to be able to cooperate on a single drawing, which means each shape must know when it is changed, if it has been communicated to other users that the shape is changed, wether it is locked by some user that is actually dragging it etc..
You can do it in simple OOP, implementing relevant parts in Shape or whatever your root class is, but you will the pollute all your setters with calls like "this.setDirty(true)" or similar stuff.
Instead, you decide to go AOP and implement it in an aspect. In this case, you can easily add an advice after all setters, but you'll also need to store a "dirty" boolean, or even a list of properties that changed if you want to optimize your network protocol sending only deltas of changes.
You could implement it like
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
}
This is nothing you cannot do with common AOP, is simply a matter of encapsulating in a single compilation unit advice, data needed by that advice, and methods that will eventually operate on that data.
Java does not support multiple inheritance or mixin. But with ITD's you can make Scala like Traits or Ruby like Mixins.
Here is an example taking advantage of JPA and Spring's Configurable:
Interface:
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);
}
}
Now any class that implements DomainNotify will get the ITD methods weaved in.
@Entity
@Configurable
public class MyJPAObject implements DomainNotify {
}
Take a look at Spring ROO. It is a rapid dev. env using Spring. I see it as a Ruby on Rails but in java with Spring ;-)
It use ITD a lot to generate getter, setter, toString etc... based on the attributes you define when you create your Class.
Spring Roo