David_W (70) [Avatar] Offline
#1
The aspect in listing 5.4 actually does the equivalent of
public void setAddress(String address) {
String oldValue = this.address;
this.address = address;
propertyChangeSupport.firePropertyChange("address", oldValue, address);
}
which is preferable to the implementation that you have in listing 5.2. Listing 5.2 would result in an event listener still seeing the old value if it called getAddress on the subject of the event.
David_W (70) [Avatar] Offline
#2
Re: BeanMakerAspect in listing 5.4 better than listing 5.2
By the way, for correct bean standards, shouldn't the execution pointcut actually be
execution(void Customer+.set*(..))? And, even though the args pointcut enforces that there is only 1 parm, maybe execution(void Customer+.set*(*)) would be even clearer.

For reduced memory use, better performance, and allowing you to remove the beanCreation pointcut, you could also use lazy instantiation of propertyChangeSupport - only instantiating it in addPropertyChangeListener, and checking for null in removePropertyChangeListener, and adding if(bean.propertyChangeSupport!=null) in the beanPropertyChange pointcut.

And the new value in the PropertyChangeEvent is only correct if the setter doesn't perform any transformation to the parameter value.
David_W (70) [Avatar] Offline
#3
Re: BeanMakerAspect in listing 5.4 better than listing 5.2
If you prefer to keep the beanCreation pointcut, perhaps listing 5.7 should modify the pointcut as execution(BeanSupport+.new(..)) && this(bean).
ramnivas (171) [Avatar] Offline
#4
Re: BeanMakerAspect in listing 5.4 better than listing 5.2
As usual, you are making good points.

I am keeping beanCreation() and advice to it to set the PropertyChangeSupport field. I think depending on the context, lazy style may or may not be preferable.

Thanks for pointing to use execution(BeanSupport+.new(..)) && this(bean). I improved it further to use initialization(BeanSupport+.new(..)) && this(bean). This way if a class has multiple nested constructors, only the first called constructor will lead to creating and setting the field. With execution(), one object will be created for each constructor in a chain. While still correct from external point of view, it will lead to wasteful objects.

-Ramnivas