众所周知,spring aop中一个advisor=advice or methodinterceptor + pointcut,之后将不同的advisor调用ProxyFactory的addAdvisor方法添加进去并排序(顺序特别重要,在最新的源码里是需要实现PriorityOrdered接口或者使用@Order注解来实现),最后调用ProxyFactory的getProxy方法得到增强,在看spring源码的时候偶尔注意到了一系列introduction和mixin的概念,附上一篇非常nice的博文:http://www.javalobby.org/java/forums/t45691.html
废话不多说,上代码:
package com.rabbit.spring.aop.introduction;import org.springframework.aop.IntroductionAdvisor;import org.springframework.aop.framework.ProxyFactory;public class IntroductionExample { public static void main(String[] args) { TargetBean target = new TargetBean(); target.setName("Ethan"); IntroductionAdvisor advisor = new IsModifiedAdvisor(); ProxyFactory pf = new ProxyFactory(); pf.setTarget(target); pf.addAdvisor(advisor); pf.setOptimize(true); TargetBean proxy = (TargetBean) pf.getProxy(); IsModified proxyInterface = (IsModified) proxy; System.out.println("is target bean " + (proxy instanceof TargetBean)); System.out.println("is ismodified " + (proxy instanceof IsModified)); System.out.println("changed? " + proxyInterface.isModified()); proxy.setName("Zhang"); System.out.println("changed? " + proxyInterface.isModified()); proxy.setName("Li"); System.out.println("changed? " + proxyInterface.isModified()); }}
package com.rabbit.spring.aop.introduction;public interface IsModified { boolean isModified();}
package com.rabbit.spring.aop.introduction;import org.springframework.aop.support.DefaultIntroductionAdvisor;public class IsModifiedAdvisor extends DefaultIntroductionAdvisor { /** * */ private static final long serialVersionUID = 1L; public IsModifiedAdvisor() { super(new IsModifiedMixin()); }}
package com.rabbit.spring.aop.introduction;import java.lang.reflect.Method;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import org.aopalliance.intercept.MethodInvocation;import org.springframework.aop.support.DelegatingIntroductionInterceptor;public class IsModifiedMixin extends DelegatingIntroductionInterceptor implements IsModified { /** * */ private static final long serialVersionUID = 1L; private boolean isModified = false; private MapmethodCache = new ConcurrentHashMap<>(); @Override public boolean isModified() { return isModified; } public Object invoke(MethodInvocation invocation) throws Throwable { if (!isModified) { if ((invocation.getMethod().getName().startsWith("set")) && (invocation.getArguments().length == 1)) { 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); } private Method getGetter(Method setter) { Method getter = methodCache.get(setter); if (getter != null) { return getter; } String getterName = setter.getName().replaceFirst("set", "get"); try { getter = setter.getDeclaringClass().getMethod(getterName, (Class []) null); methodCache.put(setter, getter); return getter; } catch (NoSuchMethodException ex) { return null; } }}
package com.rabbit.spring.aop.introduction;public class TargetBean { /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } private String name; }
运行结果:
is target bean true
is ismodified true
changed? false
changed? true
changed? true
github地址:https://github.com/stillotherguy/javaopensource/tree/master/src/main/java/com/rabbit/spring/aop/introduction
可以自己copy一份运行一下,要想知道其中奥秘,spring aop源码是必须了解的,以后有空写一下!