【Spring 源码】AOP 的加载原理(二)
文章目录
一、选择创建策略
主要代码:DefaultAopProxyFactory#createAopProxy()
在之前讲到 DefaultAopProxyFactory 是默认的创建代理的工厂类,会根据传入的被代理类来选择不同的创建策略。
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
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.");
}
// 如果是接口或者是 Proxy 类型的 Bean 要创建 JDK 动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 其他情况会创建 CGLib 动态代理
return new ObjenesisCglibAopProxy(config);
}
else {
// 使用 JDK 动态代理
return new JdkDynamicAopProxy(config);
}
}
1. JDK 动态代理
JDK 动态代理
【1】获取被代理的接口
主要代码:JdkDynamicAopProxy#getProxy()
在这个过程中,主要是通过 AopProxyUtils.completeProxiedInterfaces()
进行被代理接口的筛选,在 Java 中,我们都知道一个类只能继承一个父类,但是可以实现多个接口,所以要找到被代理的接口需要做一堆工作。
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
// 获取需要代理的接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 找 EqualsAndHashCode 方法
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// JDK 动态代理的获取目标类的主要方法
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
【2】JDK 动态代理主要处理方法
主要代码:JdkDynamicAopProxy#invoke()
在方法中,会发现 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
这么一行方法,这边主要是使用了责任链模式对 Advisors 进行封装成链,以便后续继续使用。
@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)) {
return equals(args[0]);
}
// 目标未实现 hashCode 方法
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
// 直接反射调用
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 获取目标类
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取目标方法的拦截器调用链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 如果拦截链为空,也就是当前的方法上没有任何通知并且方法访问权限还是 public 的
if (chain.isEmpty()) {
// 对给定的参数进行类型处理然后传入目标方法中
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 创建 ReflectiveMethodInvocation,会和 CGLib 创建的 MethodInvocation 有区别
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 进行拦截器的方法调用
retVal = invocation.proceed();
}
// 获取返回值类型
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
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()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
【3】将 Advisors 封装成调用链
主要代码:this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// 获取注册器
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 获取 Advisors
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
// 获取目标类
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
// 循环 Advisors
for (Advisor advisor : advisors) {
// 如果 advisor 属于 PointcutAdvisor
if (advisor instanceof PointcutAdvisor) {
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);
}
// 如果匹配到,则需要包装成 InterceptorAndDynamicMethodMatcher 添加到责任链中
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
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;
}
【4】Advisor 的实际处理方法
主要代码:ReflectiveMethodInvocation#proceed();
在 proceed()
过程中会不断进行各种 Advisor 自己处理方法的调用,如果有的 Advisor 有后续处理,则会再次调用 proceed()
。
@Override
@Nullable
public Object proceed() throws Throwable {
// 直接调用切入点的方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 获取当前要调用的通知
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 如果 Advisor 包装成了 InterceptorAndDynamicMethodMatcher,则会使用 InterceptorAndDynamicMethodMatcher 中的匹配器先进行匹配
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// 判断是否要调用通知
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
// 如果匹配成功,则会调用 InterceptorAndDynamicMethodMatcher 中注册的拦截器
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// 如果不需要调用当前通知,则继续查找拦截链中的其他通知
return proceed();
}
}
else {
// 各种 Advisor 调用自己的处理方法,有的 Advisor 执行完自己的处理方法会再次调用 proceed()
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
2. CGLib 动态代理
CGLib 动态代理和 JDK 动态代理的区别是 CGLib 动态代理会多一个 CallbackFilter 的处理。
【1】获取代理创建的 Bean
主要代码:CglibAopProxy#getProxy()
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
// 获取 aop 的目标类
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);
}
}
// 对类的方法进行访问权限的校验
validateClassIfNecessary(proxySuperClass, classLoader);
// 初始化 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));
// 设置动态代理回调
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// 设置回调过滤器
enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// 创建被代理的目标类实例
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) {
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
【3】CGLib 主要处理方法
主要代码:DynamicAdvisedInterceptor#intercept()
等待目标类以及 CGLib 创建完以后,需要等待目标类实际调用方法才会调用 intercept()
。而在此方法中大部分内容和 JDK 动态代理是相同的。
@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) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 获取目标类
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取拦截链并对目标方法和目标类进行匹配,如果匹配成功,则会创建 InterceptorAndDynamicMethodMatcher
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 如果拦截链为空,也就是当前的方法上没有任何通知并且方法访问权限还是 public 的
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// 对给定的参数进行类型处理然后传入目标方法中
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 如果目标方法上有通知,则会执行注册的通知方法,虽然和 JDK 动态代理创建的 MethodInvocation 不同,但是实际调用的和 JDK 动态代理是同一个方法
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) {
AopContext.setCurrentProxy(oldProxy);
}
}
}