| /*
 Pro Spring
 By Rob Harrop
 Jan Machacek
 ISBN: 1-59059-461-4
 Publisher: Apress
 */
 
 
 
 ///////////////////////////////////////////////////////////////////////////////////////
 
 public interface IsModified {
 
 public boolean isModified();
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////////////
 
 import org.springframework.aop.support.DefaultIntroductionAdvisor;
 
 public class IsModifiedAdvisor extends DefaultIntroductionAdvisor {
 
 public IsModifiedAdvisor() {
 super(new IsModifiedMixin());
 }
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////////////
 
 public class TargetBean {
 
 private String name;
 
 public void setName(String name) {
 this.name = name;
 }
 
 public String getName() {
 return name;
 }
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////////////
 
 import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Map;
 
 import org.aopalliance.intercept.MethodInvocation;
 import org.springframework.aop.support.DelegatingIntroductionInterceptor;
 
 public class IsModifiedMixin extends DelegatingIntroductionInterceptor
 implements IsModified {
 
 private boolean isModified = false;
 
 private Map methodCache = new HashMap();
 
 public boolean isModified() {
 return isModified;
 }
 
 public Object invoke(MethodInvocation invocation) throws Throwable {
 
 if (!isModified) {
 if ((invocation.getMethod().getName().startsWith("set"))
 && (invocation.getArguments().length == 1)) {
 
 // invoke the corresponding get method to see
 // if the value has actually changed
 Method getter = getGetter(invocation.getMethod());
 
 if (getter != null) {
 // modification check is unimportant
 // for write only methods
 Object newVal = invocation.getArguments()[0];
 Object oldVal = getter.invoke(invocation.getThis(), null);
 
 if((newVal == null) && (oldVal == null)) {
 isModified = false;
 } else if((newVal == null) && (oldVal != null)) {
 isModified = true;
 } else if((newVal != null) && (oldVal == null)) {
 isModified = true;
 } else {
 isModified = (!newVal.equals(oldVal));
 }
 }
 
 }
 }
 
 return super.invoke(invocation);
 }
 
 private Method getGetter(Method setter) {
 Method getter = null;
 
 // attempt cache retrieval.
 getter = (Method) methodCache.get(setter);
 
 if (getter != null) {
 return getter;
 }
 
 String getterName = setter.getName().replaceFirst("set", "get");
 try {
 getter = setter.getDeclaringClass().getMethod(getterName, null);
 
 // cache getter
 synchronized (methodCache) {
 methodCache.put(setter, getter);
 }
 
 return getter;
 } catch (NoSuchMethodException ex) {
 // must be write only
 return null;
 }
 }
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////
 import org.springframework.aop.IntroductionAdvisor;
 import org.springframework.aop.framework.ProxyFactory;
 
 public class IntroductionExample {
 
 public static void main(String[] args) {
 // create the target
 TargetBean target = new TargetBean();
 target.setName("Name");
 
 // create the advisor
 IntroductionAdvisor advisor = new IsModifiedAdvisor();
 
 // create the proxy
 ProxyFactory pf = new ProxyFactory();
 pf.setTarget(target);
 pf.addAdvisor(advisor);
 pf.setOptimize(true);
 
 TargetBean proxy = (TargetBean)pf.getProxy();
 IsModified proxyInterface = (IsModified)proxy;
 
 // test interfaces
 System.out.println("Is TargetBean?: " + (proxy instanceof TargetBean));
 System.out.println("Is IsModified?: " + (proxy instanceof IsModified));
 
 // test is modified implementation
 System.out.println("Has been modified?: " + proxyInterface.isModified());
 proxy.setName("Rob Harrop");
 System.out.println("Has been modified?: " + proxyInterface.isModified());
 proxy.setName("Joe Schmoe");
 System.out.println("Has been modified?: " + proxyInterface.isModified());
 
 }
 }
 
 
 
 |