论坛首页 Java企业应用论坛

初探spring aop内部实现

浏览 7267 次
精华帖 (1) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-12-21  
AOP功能强大,但是spring是如何来实现AOP技术的呢?
SPRING是通过动态代理来实现AOP的,SPRING内部提供了2种实现机制
1.如果是有接口声明的类进行AOP,spring调用的是java.lang.reflection.Proxy类来做处理

org.springframework.aop.framework.JdkDynamicAopProxy
	public Object getProxy(ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			Class targetClass = this.advised.getTargetSource().getTargetClass();
			logger.debug("Creating JDK dynamic proxy" +
					(targetClass != null ? " for [" + targetClass.getName() + "]" : ""));
		}
		Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

org.springframework.aop.framework.ReflectiveMethodInvocation
public Object proceed() throws Throwable {
		//	We start with an index of -1 and increment early.
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}

		Object interceptorOrInterceptionAdvice =
		    this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
			InterceptorAndDynamicMethodMatcher dm =
			    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
				return dm.interceptor.invoke(this);
			}
			else {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				return proceed();
			}
		}
		else {
			// It's an interceptor, so we just invoke it: The pointcut will have
			// been evaluated statically before this object was constructed.
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}


2.如果是没有接口声明的类呢?SPRING通过CGLIB包和内部类来实现

private static class StaticUnadvisedInterceptor implements MethodInterceptor, Serializable {

		private final Object target;

		public StaticUnadvisedInterceptor(Object target) {
			this.target = target;
		}

		public Object intercept(Object proxy, Method method, Object[] args,
				MethodProxy methodProxy) throws Throwable {

			Object retVal = methodProxy.invoke(target, args);
			return massageReturnTypeIfNecessary(proxy, target, retVal);
		}
	}


	/**
	 * Method interceptor used for static targets with no advice chain, when the
	 * proxy is to be exposed.
	 */
	private static class StaticUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {

		private final Object target;

		public StaticUnadvisedExposedInterceptor(Object target) {
			this.target = target;
		}

		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			try {
				oldProxy = AopContext.setCurrentProxy(proxy);
				Object retVal = methodProxy.invoke(target, args);
				return massageReturnTypeIfNecessary(proxy, target, retVal);
			}
			finally {
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}


	/**
	 * Interceptor used to invoke a dynamic target without creating a method
	 * invocation or evaluating an advice chain. (We know there was no advice
	 * for this method.)
	 */
	private class DynamicUnadvisedInterceptor implements MethodInterceptor, Serializable {

		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object target = advised.getTargetSource().getTarget();
			try {
				Object retVal = methodProxy.invoke(target, args);
				return massageReturnTypeIfNecessary(proxy, target, retVal);
			}
			finally {
				advised.getTargetSource().releaseTarget(target);
			}
		}
	}


	/**
	 * Interceptor for unadvised dynamic targets when the proxy needs exposing.
	 */
	private class DynamicUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {

		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			Object target = advised.getTargetSource().getTarget();
			try {
				oldProxy = AopContext.setCurrentProxy(proxy);
				Object retVal = methodProxy.invoke(target, args);
				return massageReturnTypeIfNecessary(proxy, target, retVal);
			}
			finally {
				AopContext.setCurrentProxy(oldProxy);
				advised.getTargetSource().releaseTarget(target);
			}
		}
	}



我们自己也可以来试试
1.jdk proxy方式

先来一个接口
IHelloWorld.java

package kris.aop.test;

public interface IHelloWorld {

	public void print(String name);
	
	public void write(String sth);
}



再来一个实现

HelloWorld.java

package kris.aop.test;

public class HelloWorld implements IHelloWorld {

	public void print(String name){
		System.out.println("HelloWorld "+name);
	}

	public void write(String sth) {
		System.out.println("write "+sth);
		
	}

}


代理类

DefaultInvocationHandler.java

package kris.aop.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class DefaultInvocationHandler implements InvocationHandler {

	/**
	 * 替换外部class调用的方法
	 * obj		外部已经已经包装好InvocationHandler的实例
	 * method	外部方法
	 * args		方法参数
	 */
	public Object invoke(Object obj, Method method, Object[] args)
			throws Throwable {
		String s1 []={"kris"};
		String s2 []={"anyone"};
		IHelloWorld ihw=new HelloWorld();
		System.out.println("start!");
		method.invoke(ihw,args);
		method.invoke(ihw,s1);
		Object o=method.invoke(ihw,s2);
		System.out.println("stop!");
		return o;
	}

}


测试类
Test.java

package kris.aop.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Test {

	public static void main(String args []){
		Class clazz = new HelloWorld().getClass();
		ClassLoader cl = clazz.getClassLoader();
		Class classes [] = clazz.getInterfaces();
		InvocationHandler ih=new DefaultInvocationHandler();
		//用InvocationHandler给HelloWorld进行AOP包装
		IHelloWorld ihw=(IHelloWorld) Proxy.newProxyInstance(cl,classes,ih);
		ihw.print("test");
		ihw.write("test");
	}
}



2.用CGLIB包实现,首先不要忘了引入那个包

package kris.aop.cglib.test;

public class HelloWorld {

	public void print(String name){
		System.out.println("HelloWorld "+name);
	}

	public void write(String sth) {
		System.out.println("write "+sth);
		
	}
	public void print(){
		System.out.println("HelloWorld");
	}

}


代理类(没用内部类,看起来清楚点)

package kris.aop.cglib.test;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class MethodInterceptorImpl implements MethodInterceptor {

	public Object intercept(Object obj, Method method, Object[] args,
			MethodProxy proxy) throws Throwable {

		System.out.println(method);

		proxy.invokeSuper(obj, args);

		return null;
	}
}


测试类
package kris.aop.cglib.test;

import net.sf.cglib.proxy.Enhancer;

public class Test {

	public static void main(String[] args) {

		Enhancer enhancer = new Enhancer();

		enhancer.setSuperclass(HelloWorld.class);
		//设置回调方法实现类
		enhancer.setCallback(new MethodInterceptorImpl());
		//实例化已经添加回调实现的HELLOWORLD实例
		HelloWorld my = (HelloWorld) enhancer.create();

		my.print();
	}

}
   发表时间:2007-02-01  
清楚 谢谢
0 请登录后投票
   发表时间:2007-02-02  
初级会员都这么高.....
0 请登录后投票
   发表时间:2007-04-14  
引用
初级会员都这么高
初级才是高手,楼主,现在在研究Spring AOP的拦截具体的调用过程,能不能解释的稍微详细些,最上面的两段代码.
0 请登录后投票
   发表时间:2007-04-14  
LargeBean 写道
初级会员都这么高.....

高不高,可不是拿论坛上面的等级来区分哦!!!
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics