引入的基本知识
Spring讲引用当成一种特殊的通知,具体讲些,是一种特殊的包围通知,因为引用只能用在类这一等级上,所以我们使用引用时不能用切入点,引入为类增加了新的接口实现,而切入点定义一个通知涉及的那些方法
背景
假设有如下案例,我们有一个javaBean,其中有setter和getter方法,当对象被属性被改变的以后,进行持久化操作,没有改变时候,不进行持久化操作,但是,我们如何确定javaBean是否真的进行改变了呢?如果用切入点的方式,我们就必须对每一个可能修改对象属性的方法都进行通知检查,这样会产生很多冗余代码,在这里使用引入恰大好处,具体做大如下:
首先,定义IsModified接口,此接口表示对象是否被修改
public interface IsModified ... {
public boolean isModified();
}
BeanOne.java
public class BeanOne ... {
private String name;
public String getName() ...{
return name;
}
public void setName(String name) ...{
this.name = name;
}
}
混合体实现了IsModified接口,继承了DelegatingIntroductionInterceptor
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))
...{
//执行相应的getter方法判断是否真正的通过set方法修改了成员变量
Method getter=getGetter(invocation.getMethod());
if(getter!=null)...{
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);
}
//从缓存中读取get反射方法
private Method getGetter(Method setter)...{
Method getter=null;
getter=(Method)methodCache.get(setter);
if(getter!=null)...{
return getter;
}
String getterName=setter.getName().replaceFirst("set", "get");
try ...{
getter=setter.getDeclaringClass().getMethod(getterName,null);
synchronized(methodCache)...{
methodCache.put(setter, getter);
}
return getter;
} catch (SecurityException e) ...{
e.printStackTrace();
return null;
} catch (NoSuchMethodException e) ...{
e.printStackTrace();
return null;
}
}
}
测试代码:
import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.ControlFlowPointcut;
import org.springframework.aop.support.DefaultIntroductionAdvisor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
public class Test ... {
/** *//**
* @param args
*/
public static void main(String[] args) ...{
BeanOne one=new BeanOne();
one.setName("gaoxiang");
BeanOne proxyOne;
Advisor advisor=new DefaultIntroductionAdvisor(new IsModifiedMixin());
//创建BeanOne代理
ProxyFactory pf1=new ProxyFactory();
pf1.addAdvisor(advisor);
pf1.setTarget(one);
pf1.setOptimize(true);
BeanOne proxy=(BeanOne)pf1.getProxy();
IsModified proxyInterface=(IsModified)proxy;
System.out.println("Is BeanOne?"+(proxy instanceof BeanOne));
System.out.println("Is IsModified?"+(proxy instanceof IsModified));
//测试程序是否经过修改
System.out.println("has bean IsModified?"+proxyInterface.isModified());
proxy.setName("gaoxiang");
System.out.println("has bean IsModified?"+proxyInterface.isModified());
proxy.setName("yulihua");
System.out.println("has bean IsModified?"+proxyInterface.isModified());
}
}
结果:
Is BeanOne?true
Is IsModified?true
has bean IsModified?false
has bean IsModified?false
has bean IsModified?true
后记:
我们创建代理的时候,设置了Optimize标志为true,强制使用CGLIB代理,如果我们使用JDK代理,则代理的混合体将不是一个类的实例,也就是说,我们使用CGLIB代理,Is BeanOne和Is IsModifie都为true,如果使用JDK代理,则Is Bean就为false