SpringAOP从入门到源码分析大全(三)ProxyFactory源码分析

文章目录

系列文档索引

SpringAOP从入门到源码分析大全(一)熟悉动态代理
SpringAOP从入门到源码分析大全(二)熟悉ProxyFactory
SpringAOP从入门到源码分析大全(三)ProxyFactory源码分析
SpringAOP从入门到源码分析大全(四)SpringAOP的源码分析
SpringAOP从入门到源码分析大全(五)手写一个编程式AOP

五、ProxyFactory源码分析

1、案例

java 复制代码
UserService userService = new UserService();
// spring 将cglib和jdk动态代理合二为一了,如果有接口,就会走jdk代理,如果只有类,就会走cglib代理
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(userService);
// 可以设置多个Advice,会形成代理链
proxyFactory.addAdvice(new MyBeforeAdvice());
proxyFactory.addAdvice(new MyAroundAdvice());
proxyFactory.addAdvice(new MyAfterAdvice());

proxyFactory.addAdvisor(new PointcutAdvisor() {
    @Override
    public Pointcut getPointcut() {
        return new Pointcut() {
            @Override
            public ClassFilter getClassFilter() {
                return new ClassFilter() {
                    @Override
                    public boolean matches(Class<?> clazz) {
                        // 类匹配器
                        return false;
                    }
                };
            }

            @Override
            public MethodMatcher getMethodMatcher() {
                // 方法匹配器
                return new MethodMatcher() {
                    @Override
                    public boolean matches(Method method, Class<?> targetClass) {
                        return false;
                    }

                    @Override
                    public boolean isRuntime() {
                        return false; // 如果为true时,下面的参数matches就会生效
                    }

                    @Override
                    public boolean matches(Method method, Class<?> targetClass, Object... args) {
                        return false;
                    }
                };
            }
        };
    }

    @Override
    public Advice getAdvice() {
        return new MyAfterAdvice();
    }

    // 没用
    @Override
    public boolean isPerInstance() {
        return true;
    }
});

UserService proxy = (UserService) proxyFactory.getProxy();

proxy.test();

2、认识TargetSource

(1)何时用到TargetSource

我们在调用proxyFactory.setTarget方法时,是将原始对象封装为了SingletonTargetSource。

SingletonTargetSource实现了TargetSource接口,相当于非常简单的一个TargetSource。

java 复制代码
// 动态目标源可以支持池化、热插拔等。
public interface TargetSource extends TargetClassAware {

	// 返回TargetSource返回的目标类型。
	@Override
	@Nullable
	Class<?> getTargetClass();

	// true表示目标不可变,意味着会缓存Target
	boolean isStatic();

	// 返回目标实例。在AOP框架调用AOP方法调用的"目标"之前立即调用。
	@Nullable
	Object getTarget() throws Exception;

	// 释放从getTarget()方法获得的给定目标对象(如果有的话)。
	void releaseTarget(Object target) throws Exception;

}

其实,AOP代理的对象,每次调用代理对象的方法时,获取的原始对象就是从TargetSource 的getTarget方法中获取的,这就意味着具备了很强的灵活性。

(2)@Lazy的原理

java 复制代码
@Autowired
private UserService userService;

在属性注入时,使用@Lazy注解,并不会初始化Bean,而是将代理对象赋值给了属性。

我们看一下@Lazy属性赋值的源码:

java 复制代码
// org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver#buildLazyResolutionProxy
protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {
	BeanFactory beanFactory = getBeanFactory();
	Assert.state(beanFactory instanceof DefaultListableBeanFactory,
			"BeanFactory needs to be a DefaultListableBeanFactory");
	final DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;

	TargetSource ts = new TargetSource() {
		@Override
		public Class<?> getTargetClass() {
			return descriptor.getDependencyType();
		}
		@Override
		public boolean isStatic() {
			return false;
		}
		@Override
		public Object getTarget() {
			Set<String> autowiredBeanNames = (beanName != null ? new LinkedHashSet<>(1) : null);
			Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);
			if (target == null) {
				Class<?> type = getTargetClass();
				if (Map.class == type) {
					return Collections.emptyMap();
				}
				else if (List.class == type) {
					return Collections.emptyList();
				}
				else if (Set.class == type || Collection.class == type) {
					return Collections.emptySet();
				}
				throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
						"Optional dependency not present for lazy injection point");
			}
			if (autowiredBeanNames != null) {
				for (String autowiredBeanName : autowiredBeanNames) {
					if (dlbf.containsBean(autowiredBeanName)) {
						dlbf.registerDependentBean(autowiredBeanName, beanName);
					}
				}
			}
			return target;
		}
		@Override
		public void releaseTarget(Object target) {
		}
	};

	ProxyFactory pf = new ProxyFactory();
	pf.setTargetSource(ts);
	Class<?> dependencyType = descriptor.getDependencyType();
	if (dependencyType.isInterface()) {
		pf.addInterface(dependencyType);
	}
	return pf.getProxy(dlbf.getBeanClassLoader());
}

上面的源码可以看出,就是将属性赋值了一个代理对象,而TargetSource 的getTarget方法,就是从容器中获取目标对象的Bean进行返回。很巧妙的实现了懒加载。

(3)应用TargetSource

实际上我们日常开发中,很少会用到TargetSource。

我们也可以使用TargetSource实现懒加载、池化(每次获取Target都是从池子里获取)、热插拔(每次获取Target都是重新获取)。

3、ProxyFactory选择cglib或jdk动态代理原理

ProxyFactory在生成代理对象之前需要决定到底是使用JDK动态代理还是CGLIB技术:

java 复制代码
// org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	// 是GraalVM 就直接用jdk代理
	// Optimize == true或者isProxyTargetClass == true 或者配置了接口,就走jdk
	if (!NativeDetector.inNativeImage() &&
			(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.");
		}
		// 被代理的类是接口 或 被代理的类已经是jdk代理类了 或 lambda表达式 就用jdk
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}

然后获取代理类的方法,就是jdk和cglib代理的逻辑。

4、jdk代理获取代理方法的逻辑

JdkDynamicAopProxy实现了InvocationHandler方法,JdkDynamicAopProxy调用其getProxy方法,执行目标方法就会执行JdkDynamicAopProxy的invoke方法:

java 复制代码
	@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 {
			// 如果接口中没有定义equals()方法,那么直接调用,不走代理
			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...
				// 也是直接调用Advised接口中的方法,不走代理逻辑
				// 其实就是利用代理对象获取ProxyFactory中的信息
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;
			// 如果ProxyFactory的exposeProxy为true,则将代理对象设置到currentProxy这个ThreadLocal中去
			// 如果使用@EnableAspectJAutoProxy注解,需要手动将该参数设置为true,默认为false
			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.
			// 代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成Interceptor 代理链
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// Check whether we have any advice. If we don't, we can fall back 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.
				// 如果没有Advice,则直接调用对应方法
				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);
			}
		}
	}

(1)getInterceptorsAndDynamicInterceptionAdvice获取拦截器链

java 复制代码
// org.springframework.aop.framework.AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
	// 代理对象在执行某个方法时,会根据当前ProxyFactory中所设置的Advisor根据当前method再次进行过滤
	MethodCacheKey cacheKey = new MethodCacheKey(method);
	// 注意这个List,表示的就是Advice,有缓存。
	List<Object> cached = this.methodCache.get(cacheKey);
	if (cached == null) {
		cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
				this, method, targetClass);
		this.methodCache.put(cacheKey, cached);
	}
	return cached;
}
java 复制代码
// org.springframework.aop.framework.DefaultAdvisorChainFactory#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();
	// 从ProxyFactory中拿到所设置的Advice,(添加时被封装成了DefaultPointcutAdvisor)
	// 添加的时候会控制顺序
	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) {
		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;
				// 再匹配方法
				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) {
					// 如果匹配,则将Advisor封装成Interceptor,当前Advisor中的Advice可能既是MethodBeforeAdvice也是ThrowingAdvice,除了around的都需要包装
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
					if (mm.isRuntime()) { // true 需要包装Interceptor,会将参数传过来进行判断
						// 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.addAll(Arrays.asList(interceptors));
					}
				}
				// 最终,interceptorList中存储的是当前正在执行的Method所匹配的MethodInterceptor,可能是动态的,也可能是非动态的。
				// 找到Method所匹配的MethodInterceptor后,就会开始调用这些MethodInterceptor,如果是动态的,会额外进行方法参数的匹配判断
			}
		}
		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;
}

(2)包装AfterReturningAdvice、MethodBeforeAdvice为MethodInterceptor

包装的MethodInterceptor和around的效果是一样的。


ThrowsAdviceInterceptor:复杂一些,会将异常类型匹配出来

(3)总结

在构造JdkDynamicAopProxy对象时,会先拿到被代理对象自己所实现的接口,并且额外的增加SpringProxy、Advised、DecoratingProxy三个接口,组合成一个Class[],并赋值给proxiedInterfaces属性

并且检查这些接口中是否定义了equals()、hashcode()方法

执行Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this),得到代理对象,JdkDynamicAopProxy作为InvocationHandler,代理对象在执行某个方法时,会进入到JdkDynamicAopProxy的**invoke()**方法中

5、cglib代理获取代理方法的逻辑

CglibAopProxy的getProxy方法逻辑:

java 复制代码
// org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader)
@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;
		// 如果被代理类本身就已经是cglib所生成的类了
		if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
			// 获取真正的被代理类
			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 ClassLoaderAwareGeneratorStrategy(classLoader));
		// 获取和被代理类所匹配的Advisor
		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);
	}
}

(1)getCallbacks获取callback方法

java 复制代码
// org.springframework.aop.framework.CglibAopProxy#getCallbacks
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
	// Parameters used for optimization choices...
	boolean isFrozen = this.advised.isFrozen();
	boolean exposeProxy = this.advised.isExposeProxy();
	boolean isStatic = this.advised.getTargetSource().isStatic();

	// Choose an "aop" interceptor (used for AOP calls).
	// 重要
	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.
	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.
	if (isStatic && isFrozen) {
		Method[] methods = rootClass.getMethods();
		Callback[] fixedCallbacks = new Callback[methods.length];
		this.fixedInterceptorMap = CollectionUtils.newHashMap(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(method, 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;
}
java 复制代码
// org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept
@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() && CglibMethodInvocation.isMethodProxyCompatible(method)) {
			// 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 = invokeMethod(target, method, argsToUse, methodProxy);
		}
		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);
		}
	}
}

(2)总结

创建Enhancer对象

设置Enhancer的superClass为通过ProxyFactory.setTarget()所设置的对象的类

设置Enhancer的interfaces为通过ProxyFactory.addInterface()所添加的接口,以及SpringProxy、Advised、DecoratingProxy接口

设置Enhancer的Callbacks为DynamicAdvisedInterceptor

最后创建一个代理对象,代理对象在执行某个方法时,会进入到DynamicAdvisedInterceptor的intercept()方法中

6、执行器链执行逻辑

java 复制代码
// org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
@Override
@Nullable
public Object proceed() throws Throwable {
	// We start with an index of -1 and increment early.
	// 当调用完了最后一个interceptor后会就执行被代理方法
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		// 调用目标方法
		return invokeJoinpoint();
	}

	// currentInterceptorIndex  初始值 - 1
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

	// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该Interceptor
	// 如果没有匹配则递归调用proceed()方法,调用下一个interceptor
	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.
			// 不匹配则执行下一个MethodInterceptor
			return proceed();
		}
	}
	else {
		// It's an interceptor, so we just invoke it: The pointcut will have
		// been evaluated statically before this object was constructed.
		// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed方法进行递归
		// 比如MethodBeforeAdviceInterceptor
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

在使用ProxyFactory创建代理对象之前,需要往ProxyFactory先添加Advisor

代理对象在执行某个方法时,会把ProxyFactory中的Advisor拿出来和当前正在执行的方法进行匹配筛选

把和方法所匹配的Advisor适配成MethodInterceptor

把和当前方法匹配的MethodInterceptor链,以及被代理对象、代理对象、代理类、当前Method对象、方法参数封装为MethodInvocation对象

调用MethodInvocation的proceed()方法,开始执行各个MethodInterceptor以及被代理对象的对应方法

按顺序调用每个MethodInterceptor的invoke()方法,并且会把MethodInvocation对象传入invoke()方法

直到执行完最后一个MethodInterceptor了,就会调用invokeJoinpoint()方法,从而执行被代理对象的当前方法

相关推荐
遇见你真好。6 分钟前
自定义注解进行数据脱敏
java·springboot
NMBG229 分钟前
[JAVAEE] 面试题(四) - 多线程下使用ArrayList涉及到的线程安全问题及解决
java·开发语言·面试·java-ee·intellij-idea
像污秽一样29 分钟前
Spring MVC初探
java·spring·mvc
计算机-秋大田29 分钟前
基于微信小程序的乡村研学游平台设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue
LuckyLay32 分钟前
Spring学习笔记_36——@RequestMapping
java·spring boot·笔记·spring·mapping
醉颜凉1 小时前
【NOIP提高组】潜伏者
java·c语言·开发语言·c++·算法
阿维的博客日记1 小时前
java八股-jvm入门-程序计数器,堆,元空间,虚拟机栈,本地方法栈,类加载器,双亲委派,类加载执行过程
java·jvm
qiyi.sky1 小时前
JavaWeb——Web入门(8/9)- Tomcat:基本使用(下载与安装、目录结构介绍、启动与关闭、可能出现的问题及解决方案、总结)
java·前端·笔记·学习·tomcat
lapiii3581 小时前
图论-代码随想录刷题记录[JAVA]
java·数据结构·算法·图论
RainbowSea1 小时前
4. Spring Cloud Ribbon 实现“负载均衡”的详细配置说明
java·spring·spring cloud