spring introduction aop

衆所周知,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

相關文章
相關標籤/搜索