衆所周知,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 html
廢話很少說,上代碼: java
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 Map<Method, Method> methodCache = 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 git
is ismodified true github
changed? false spring
changed? true ide
changed? true this
github地址:https://github.com/stillotherguy/javaopensource/tree/master/src/main/java/com/rabbit/spring/aop/introduction code
能夠本身copy一份運行一下,要想知道其中奧祕,spring aop源碼是必須瞭解的,之後有空寫一下! htm