SpringAOP-动态代理

SpringAOP-动态代理

在spring中,使用aop的时候通过动态代理的来实现的,一种是JDK动态代理,另一个是cglib动态代理。一般情况下用的是jdk动态代理。

JDK动态代理:代理的对象必须实现某个接口,通过在运行期间创建一个接口的实现类来完成对目标对象的代理

cglib动态代理:实现与JDK动态代理有点类似,它是通过在运行期间生成代理对象的是针对目标类扩展的子类,cglib底层是依靠ASM(开源的java字节码编辑库)操作字节码实现的,性能比jdk要强。

区别:JDK动态代理代理的对象是必须实现接口的对象,cglib动态代理的代理对象是目标扩展的子类

JDK动态代理

首先看下JDK动态代理,使用JDK中动态代理需要实现InvocationHandler接口,具体如下:

1、创建一个接口

public interface UserService {
	void add();
}

2、接口的实现类

public class UserServiceImpl implements UserService {
	@Override
	public void add() {
		System.out.println("--------------------add-----------------");
	}
}

3、实现InvocationHandler

public class MyInvocationHandler implements InvocationHandler {

	private Object traget;

	public MyInvocationHandler(Object traget){
		this.traget = traget;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //前置通知
		System.out.println("---------------before-----------");
		Object result = method.invoke(traget, args);
        //后置通知
		System.out.println("---------------after-----------");
		return result;
	}
	
}

4、测试用例

public class proxyTest {

	public static void main(String[] args) {
        //创建实例
		UserServiceImpl userService = new UserServiceImpl();
        //创建handle实例
		MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userService);
        //创建动态代理
		UserService proxyInstance = (UserService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
				userService.getClass().getInterfaces(),
				myInvocationHandler);
		proxyInstance.add();

	}

从上述的例子可以看出,具体添加前置和后置通知是在MyInvocationHandler处理中的invoke方法添加的。这个看上去还是比较简单的,那么spring中的jdk动态代理和cglib代理有什么区别呢?首先看下spring中创建动态代理。

创建动态代理

进入DefaultAopProxyFactory工厂中,可以看到实现了AopPorxyFactory接口,实现了createAopProxy()方法。

@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		//Optimize:用来控制通过CGLIB创建的代理是否使用激进的优化策略,不推荐使用,除非很了解aop
		//这个配置目前只支持CGLIB
		//ProxyTargetClass:如果设置为true,目标本身被代理
		//hasNoUserSuppliedProxyInterfaces:是否存在代理接口
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

从createAopProxy()来看,具体使用JDK动态代理还是cglic代理会经过条件判断,如果Optimize是true或者ProxyTargetClass是true,或者不存在代理接口,那么可能是cglib动态代理,但是还是需要经过是否是实现了接口,来决定使用cglib动态代理还是JDK动态代理。从spring的JDK动态代理来看。

spring Jdk动态代理

从上面的jdk动态代理来看,我们是通过invoke()方法中实现添加前后置通知,其实在spring的动态代理中也是在invoke中处理的。进入

JdkDynamicAopProxy中你会发现JdkDynamicAopProxy也实现了InvocationHandle接口。

	@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;

		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// Service invocations on ProxyConfig with the proxy config...
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;
			//目标内部调用无法实施切面中的增强,则通过此属性进行暴露代理
			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// Get as late as possible to minimize the time we "own" the target,
			// in case it comes from a pool.
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// Get the interception chain for this method.
			//获取当前拦截链
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// Check whether we have any advice. If we don't, we can fallback on direct
			// reflective invocation of the target, and avoid creating a MethodInvocation.
			if (chain.isEmpty()) {
				// We can skip creating a MethodInvocation: just invoke the target directly
				// Note that the final invoker must be an InvokerInterceptor so we know it does
				// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				//没有发生拦截器,那么直接调用切入点方法
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// We need to create a method invocation...
				//将拦截器进行封装,方便调用
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				//执行拦截器
				retVal = invocation.proceed();
			}

			// Massage return value if necessary.
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				// Special case: it returned "this" and the return type of the method
				// is type-compatible. Note that we can't help if the target sets
				// a reference to itself in another returned object.
				retVal = proxy;
			}
			else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
				throw new AopInvocationException(
						"Null return value from advice does not match primitive return type for: " + method);
			}
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				// Must have come from TargetSource.
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}

从JdkDynamicProxyFactory中的invoke实现来看,

1、判断方法是否是equals和hashcode方法

2、目标内部调用无法实施切面中的增强,则通过此属性进行暴露代理

3、获取当前拦截链

4、没有发生拦截器,那么直接调用切入点方法

5、将拦截器进行封装,通过proceed()方法执行拦截链

从上面的来看,主要的就是获取拦截链和执行拦截链

执行拦截链

进入getInterceptorsAndDynamicInterceptionAdvice方法

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
    //缓存
    MethodCacheKey cacheKey = new MethodCacheKey(method);
    List<Object> cached = this.methodCache.get(cacheKey);
    if (cached == null) {
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
            this, method, targetClass);
        this.methodCache.put(cacheKey, cached);
    }
    return cached;
}

继续看getInterceptorsAndDynamicInterceptionAdvice

	@Override
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, @Nullable Class<?> targetClass) {

		// This is somewhat tricky... We have to process introductions first,
		// but we need to preserve order in the ultimate list.
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
		Advisor[] advisors = config.getAdvisors();
		List<Object> interceptorList = new ArrayList<>(advisors.length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		Boolean hasIntroductions = null;

		for (Advisor advisor : advisors) {
			//通知是否是Pointcut通知
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					//获取方法匹配
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					boolean match;
					//是否是Introduction增强通知
					if (mm instanceof IntroductionAwareMethodMatcher) {
						if (hasIntroductions == null) {
							hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
						}
						match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
					}
					else {
						match = mm.matches(method, actualClass);
					}
					if (match) {
						//如果是增强通知
						MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
						if (mm.isRuntime()) {
							// Creating a new object instance in the getInterceptors() method
							// isn't a problem as we normally cache created chains.
							for (MethodInterceptor interceptor : interceptors) {
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						}
						else {
							//添加到interceptorList列表中
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					}
				}
			}
			else if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
					Interceptor[] interceptors = registry.getInterceptors(advisor);
					interceptorList.addAll(Arrays.asList(interceptors));
				}
			}
			else {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		return interceptorList;
	}

getInterceptorsAndDynamicInterceptionAdvice()方法主要就是获取当前需要执行的拦截器,添加在一个列表中。

接下来要看的就是执行了

执行拦截链

在这块首先会将拦截链进行封装ReflectiveMethodInvocation实例,然后通过proceed方法来执行。

@Override
	@Nullable
	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;
			Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
			if (dm.methodMatcher.matches(this.method, 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);
		}
	}

从proceed方法看上去很简单,就是遍历的去执行拦截器中的invoke方法,在这里肯定会有一个问题就是,就是我们的前置、后置、或者异常通知是怎么处理的呢。其实spring的处理的方式是在通知里面来进行处理的,首先我们看下前置通知。

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

	private final MethodBeforeAdvice advice;


	/**
	 * Create a new MethodBeforeAdviceInterceptor for the given advice.
	 * @param advice the MethodBeforeAdvice to wrap
	 */
	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}


	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		return mi.proceed();
	}

}

首先会调用before方法,然后在调用proceed(),那么后置通知呢

public class AspectJAfterAdvice extends AbstractAspectJAdvice
		implements MethodInterceptor, AfterAdvice, Serializable {

	public AspectJAfterAdvice(
			Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {

		super(aspectJBeforeAdviceMethod, pointcut, aif);
	}


	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		finally {
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}

	@Override
	public boolean isBeforeAdvice() {
		return false;
	}

	@Override
	public boolean isAfterAdvice() {
		return true;
	}

}

从invoke方法中来看,其实后置通知就是在finally方法来执行的。

从上面的用来来看,具体的通知的顺序是在具体的通知中来实现的。可以通过下面的测试用例来通过断点来看具体的调用。

测试用例:

1、创建一个接口

public interface BookService {
	void addBook();
}

2、创建接口实现类

public class BookServiceImpl implements BookService{
	@Override
	public void addBook() {
		System.out.println("-------------add book-------------");
	}
}

3、创建通知类

public class BookProxyHandler implements MethodBeforeAdvice, AfterReturningAdvice {
	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("---------------before---------------");
	}

	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("---------------after----------------");
	}
}

4、配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
		<!-- 注入bean-->
		<bean id="bookServiceImpl" class="com.jack.customtag.springjdkProxy.BookServiceImpl"></bean>
		<!--注入切入类-->
		<bean id="bookProxyHandler" class="com.jack.customtag.springjdkProxy.BookProxyHandler"></bean>

		<!--定义切入点位置-->
		<bean id="bookPointCut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
			<property name="pattern" value=".*addBook"></property>
		</bean>

		<!-- 使切入点与通知相关联,完成切面配置 -->
		<bean id="BookHandlerAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
			<property name="advice" ref="bookProxyHandler"></property>
			<property name="pointcut" ref="bookPointCut"></property>
		</bean>


		<!-- 设置代理 -->
		<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
			<!-- 代理的对象,有打印时间能力 -->
			<property name="target" ref="bookServiceImpl"></property>
			<!-- 使用切面 -->
			<property name="interceptorNames" value="BookHandlerAdvisor"></property>
			<!-- 代理接口,hw接口 -->
			<property name="proxyInterfaces" value="com.jack.customtag.springjdkProxy.BookService"></property>
		</bean>

</beans>

5、测试方法

public class JdkDynamicAopProxyTest {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-jdk" +
				"-proxy.xml");
		BookService proxy = (BookService)applicationContext.getBean("proxy");
		proxy.addBook();
	}
}

到这里spring中的jdk动态代理 的调用过程就结束了,接下来我们简单的看下spring中cglib动态代理的执行过程

cglib动态代理

简单的写一个cglib动态代理的测试

public class CglibProxyTest {

	public static void main(String[] args) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(CglibProxyTest.class);
		enhancer.setCallback(new MethodInterceptorImpl());
		CglibProxyTest cglibProxyTest = (CglibProxyTest)enhancer.create();
		cglibProxyTest.test();
	}

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

	private static class MethodInterceptorImpl implements MethodInterceptor {

		@Override
		public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
			System.out.println("----Before----:"+method);
			Object invokeSuper = methodProxy.invokeSuper(o, objects);
			System.out.println("----After----:"+method);
			return invokeSuper;
		}
	}
}

从上述测试用例来看,cglib通过创建Enhancer代理类

进入CglibAopProxy类,从getProxy来看

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
		}

		try {
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

			Class<?> proxySuperClass = rootClass;
			if (ClassUtils.isCglibProxyClass(rootClass)) {
				proxySuperClass = rootClass.getSuperclass();
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// Configure CGLIB Enhancer...
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
			//设置拦截器
			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);
			//创建动态代理实例
			// Generate the proxy class and create a proxy instance.
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		catch (CodeGenerationException | IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
					": Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (Throwable ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
    enhancer.setInterceptDuringConstruction(false);
    //设置callbacks
    enhancer.setCallbacks(callbacks);
    return (this.constructorArgs != null && this.constructorArgTypes != null ?
            enhancer.create(this.constructorArgTypes, this.constructorArgs) :
            enhancer.create());
}

从createProxyClassAndInstance方法来看,在cglib创建动态代理最主要的是设置callbacks的值,回到getProxy中的getCallbacks()方法,其实这个方法就是获取拦截器的。进入getCallbacks()方法

	private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
		// Parameters used for optimization choices...
		//设置exposeProxy属性
		boolean exposeProxy = this.advised.isExposeProxy();
		boolean isFrozen = this.advised.isFrozen();
		boolean isStatic = this.advised.getTargetSource().isStatic();

		// Choose an "aop" interceptor (used for AOP calls).
		//将拦截器封装在DynamicAdvisedInterceptor
		Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

		// Choose a "straight to target" interceptor. (used for calls that are
		// unadvised but can return this). May be required to expose the proxy.
		//cglib中需要优化的拦截器
		Callback targetInterceptor;
		if (exposeProxy) {
			targetInterceptor = (isStatic ?
					new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
		}
		else {
			targetInterceptor = (isStatic ?
					new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
		}

		// Choose a "direct to target" dispatcher (used for
		// unadvised calls to static targets that cannot return this).
		Callback targetDispatcher = (isStatic ?
				new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

		Callback[] mainCallbacks = new Callback[] {
				aopInterceptor,  // for normal advice
				targetInterceptor,  // invoke target without considering advice, if optimized
				new SerializableNoOp(),  // no override for methods mapped to this
				targetDispatcher, this.advisedDispatcher,
				new EqualsInterceptor(this.advised),
				new HashCodeInterceptor(this.advised)
		};

		Callback[] callbacks;

		// If the target is a static one and the advice chain is frozen,
		// then we can make some optimizations by sending the AOP calls
		// direct to the target using the fixed chain for that method.
		//如果目标是静态目标,并且建议链被冻结,我们可以通过使用该方法的固定链将AOP调用直接发送到目标来进行一些优化。
		if (isStatic && isFrozen) {
			Method[] methods = rootClass.getMethods();
			Callback[] fixedCallbacks = new Callback[methods.length];
			this.fixedInterceptorMap = new HashMap<>(methods.length);

			// TODO: small memory optimization here (can skip creation for methods with no advice)
			for (int x = 0; x < methods.length; x++) {
				Method method = methods[x];
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
				fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
						chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
				this.fixedInterceptorMap.put(methods.toString(), x);
			}

			// Now copy both the callbacks from mainCallbacks
			// and fixedCallbacks into the callbacks array.
			callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
			System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
			System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
			this.fixedInterceptorOffset = mainCallbacks.length;
		}
		else {
			callbacks = mainCallbacks;
		}
		return callbacks;
	}

getCallbacks()方法来看,会将拦截器进行封装,从上述的代码来看会封装很多不通情况的拦截器,我们最常用的DynamicAdvisedInterceptor,从后面的代码来看StaticUnadvisedExposedInterceptor,DynamicUnadvisedExposedInterceptor等等拦截器,具体的只看DynamicAdvisedInterceptor拦截器

进去DynamicAdvisedInterceptor类中,你会发现DynamicAdvisedInterceptor实现了MethodInterceptor接口,那么执行肯定就在intercept()方法中了。

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

		private final AdvisedSupport advised;

		public DynamicAdvisedInterceptor(AdvisedSupport advised) {
			this.advised = advised;
		}

		@Override
		@Nullable
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Object target = null;
			TargetSource targetSource = this.advised.getTargetSource();
			try {
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
				target = targetSource.getTarget();
				Class<?> targetClass = (target != null ? target.getClass() : null);
				//获取拦截链
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				//如果拦截链为空,那么直接使用原方法
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					// We can skip creating a MethodInvocation: just invoke the target directly.
					// Note that the final invoker must be an InvokerInterceptor, so we know
					// it does nothing but a reflective operation on the target, and no hot
					// swapping or fancy proxying.
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}
				else {
					// We need to create a method invocation...
					//进行调用
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null && !targetSource.isStatic()) {
					targetSource.releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

从intercept方法中来看 ,调用的方式就跟jdk动态代理一样了,首先获取拦截链,然后封装拦截链,执行拦截链。

posted @   张and强  阅读(347)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示