`
JavaCrazyer
  • 浏览: 2992474 次
  • 性别: Icon_minigender_1
  • 来自: 河南
社区版块
存档分类

Spring温习(5)--CGLIB的动态代理[附AOP内部实现讲解]

阅读更多

这篇文章紧接着上一篇静态代理和动态代理来说

前言:

到现在呢,老是讲动态代理,有的人都晕了,会说你这代理中用到的类怎么没有一个是与spring相关的呢,所以,我要说明的事,虽然现在讲的都是最普通的动态代理,但实质上就是将AOP的内部实现原理,Spring AOP之所以这么强大是因为它底层都是用动态代理来实现的,为了说明这一点,得贴出点源码来

1.如果是有接口声明的类进行AOP,spring调用的是java.lang.reflection.Proxy类来做处理
在spring的资源包中,找到org.springframework.aop.framework.JdkDynamicAopProxy这个类,在资源包的位置为spring-framework-2.5.6\src\org\springframework\aop\framework\JdkDynamicAopProxy.java,看看其中重要的代码片段

 

 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);
			}
		}
	}

 

好了,已经知道spring内部实现就是动态代理机制了,所以现在我们手动写的关于CGLIB的动态代理还是要写个小示例的。

上一篇文章中如果ServiceImpl没有实现任何接口的话,那么创建代理对象就不能使用javax.lang.Proxy这个类了,这时需要使用CGLIB了,在spring资源包中找到CGLIB的jar:spring-framework-2.5.6\lib\cglib\cglib-nodep-2.1_3.jar

然后写一个新的代理实现类CGlibProxyFactory.java

package com.javacrazyer.dao;

import java.lang.reflect.Method;

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

public class CGlibProxyFactory implements MethodInterceptor {
	private Object targetObject;

	public Object newProxy(Object targetObject) {
		this.targetObject = targetObject;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(this.targetObject.getClass());
		enhancer.setCallback(this);
		// 返回代理对象
		return enhancer.create();
	}

	/**
	 * proxy 带来对象本身 method 被拦截到的方法 args 方法的参数 methodProxy 方法的代理对象
	 */
	public Object intercept(Object proxy, Method method, Object[] args,
			MethodProxy methodProxy) throws Throwable {
		checkSecurity();
		Object ret = null;
		try {
			// 调用目标对象的真实方法
			ret = method.invoke(this.targetObject, args);
			// ret接受存在的返回值,不存在返回值则为Null
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ret;
	}

	public void checkSecurity() {
		System.out.println("--------ServiceImpl.checkSecurity()----------");
	}

}

 

 

这时测试类有所变化

package com.javacrazyer.dao;

public class TestProxy {
	public static void main(String[] args) {
		CGlibProxyFactory hander = new CGlibProxyFactory();
		//创建代理对象,这是这个代理对象是UserManagerImpl的子类
		  ServiceImpl  service = (ServiceImpl)hander.newProxy(new ServiceImpl());
		  service.outPut();
		  service.putOut();
	}
}

 

 输出结果

--------ServiceImpl.checkSecurity()----------
I am method outPut
--------ServiceImpl.checkSecurity()----------
I am method putOut

 

到目前位置,无论是前面的静态代理,javax.lang.Proxy的动态代理,还是这里的CGLIB的动态代理都是没有借助任何框架的情况下实现AOP的方法

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics