/*
Pro Spring
By Rob Harrop
Jan Machacek
ISBN: 1-59059-461-4
Publisher: Apress
*/
///////////////////////////////////////////////////////////////////////////////////////
//File: introductions.xml
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="bean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<bean id="beanTarget" class="TargetBean">
<property name="name">
<value>Rob Harrop</value>
</property>
</bean>
</property>
<property name="interceptorNames">
<list>
<value>advisor</value>
</list>
</property>
<property name="proxyTargetClass">
<value>true</value>
</property>
</bean>
<bean id="advisor" class="IsModifiedAdvisor"/>
</beans>
///////////////////////////////////////////////////////////////////////////////////////
public interface IsModified {
public boolean isModified();
}
///////////////////////////////////////////////////////////////////////////////////////
public class TargetBean {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
///////////////////////////////////////////////////////////////////////////////////////
import org.springframework.aop.support.DefaultIntroductionAdvisor;
public class IsModifiedAdvisor extends DefaultIntroductionAdvisor {
public IsModifiedAdvisor() {
super(new IsModifiedMixin());
}
}
///////////////////////////////////////////////////////////////////////////////////////
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.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class IntroductionConfigExample {
public static void main(String[] args) {
ApplicationContext ctx = new FileSystemXmlApplicationContext(
"build/introductions.xml");
TargetBean bean = (TargetBean) ctx.getBean("bean");
IsModified mod = (IsModified) bean;
// test interfaces
System.out.println("Is TargetBean?: " + (bean instanceof TargetBean));
System.out.println("Is IsModified?: " + (bean instanceof IsModified));
// test is modified implementation
System.out.println("Has been modified?: " + mod.isModified());
bean.setName("Rob Harrop");
System.out.println("Has been modified?: " + mod.isModified());
bean.setName("Joe Schmoe");
System.out.println("Has been modified?: " + mod.isModified());
}
}
|