Spring AOP 之动态代理的创建
本文旨在理清Spring的动态代理创建过程中各个组件类如何协作,共同完成代理的设置和创建,不考虑过多细节问题。
使用示例
话不多说,先上代码:
// before Advice
public class GreetingAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
String client = (String)args[0];
System.out.println("Nice to meet you ! " + client + ". ");
}
}
// 接口
public interface Waiter {
void serveTo(String name);
}
//实现类
public class NaiveWaiter implements Waiter {
@Override
public void serveTo(String name) {
System.out.println("serving " + name + "...");
}
}
//创建代理
ProxyFactory factory = new ProxyFactory();
factory.addAdvice(new GreetingAdvice());
factory.setTarget(new NaiveWaiter());
Waiter proxy = (Waiter) factory.getProxy();
proxy.greetTo("Mr. Zhang");
//result
Nice to meet you ! Mr. Zhang.
greet to Mr. Zhang...
可以看到,NaiveWaiter已经被BeforeAdvice增强了,我们来看ProxyFactory如何实现增强的。
从ProxyFactory开始
从上面的示例可以看出,ProxyFactory.getProxy()直接就创建了代理。我们跟踪一下源码,看看其调用过程,得到如下时序图:

可以看到,ProxyFactory创建代理时,先获取到AopProxyFactory,并将代理的创建工作委托给AopProxyFactory。具体的AopProxyFactory通过调用getProxy方法来来创建代理。
这里涉及到三个核心类:ProxyFactory,AopProxyFactory以及JdkDynamicAopProxy。我们来逐个分析。
ProxyFactory
ProxyFactory的功能就是创建Proxy.我们先看看他的继承结构:

- ProxyConfig: Spring创建代理的过程中需要访问的全局配置信息。主要包含一下四个:
1.proxyTargetClass:是否强制代理目标类。Spring在对bean进行自动创建代理时,会对bean进行分析,如果bean实现了某些接口,则使用JDK动态代理,如果目标类没有实现接口,则使用cglib动态代理创建目标类的子类。proxyTargetClass为true时,则上述的默认判断,直接使用cglib动态代理。
2.exposeProxy:是否在线程上下文中暴露代理对象(专题讲解)。
3.opaque:是否隐藏代理的Advised方法。opaque为false,则Spring创建的代理类都实现Advised接口,如果为true,则不实现该接口。
4.optimize:如果使用cglib创建代理,是否在创建代理时进行激进的优化。默认为false. - TargetClassAware: 规定获取代理对象的类型的方法
- Advised: 这个接口主要规定了创建代理的过程中以及代理创建后,访问相关AOP配置信息的方法,也就是说一个具体的被代理的对象上能够访问到的代理相关信息。比如规定了如何获取Adivce、Adivsor、Interceptor以及代理类实现的接口等。代理工厂需要在代理创建的过程中访问这些信息,代理对象的使用者也可以将从代理对象中获取这些信息。Spring当中创建的每个代理对象都是该接口的实现类(opaque为true的除外),以便访问代理对象的相关代理信息。
- AdvisedSupport: 代理的相关配置管理的基类。既有ProxyConfig指定的全局配置管理能力,也有Advised指定的对于每个代理的相关配置的管理能力。
- ProxyCreatorSupport:代理工厂的基类。Spring的设计是将代理的创建委托给AopProxy。这个类实现了如何获取AopProxy这个模板方法,其所有子类代理工厂都可以通过这个方法获取AopProxy,进而使用AopProxy创建代理。而如何获取AopProxy呢?ProxyCreatorSupport又将其委托给了AopProxyFactory,只要为ProxyCreatorSupport配置好了AopProxyFactory,它就可以按照既定流程(调用AopProxyFactory的getAopProxy方法)自动获取了。
分析完了类的职责以及他们如何协作的,我们再来看看JdkDynamicAopProxy是如何创建代理的:
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
可以看到,JdkDynamicAopProxy在创建代理的时候,使用的interface数组是proxiedInterfaces,传入的InvocationHandler是它自己的实例对象(this)。
我们按图索骥,先看proxiedInterfaces是从哪里来的,再看JdkDynamicAopProxy如何实现的InvocationHandler接口。
proxiedInterfaces的来源:
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}
在JdkDynamicAopProxy的构造方法中就已经完成了proxiedInterfaces的初始化,再来看详情:
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
if (specifiedInterfaces.length == 0) {
// No user-specified interfaces: check whether target class is an interface.
Class<?> targetClass = advised.getTargetClass();
if (targetClass != null) {
if (targetClass.isInterface()) {
advised.setInterfaces(targetClass);
}
else if (Proxy.isProxyClass(targetClass) || isLambda(targetClass)) {
advised.setInterfaces(targetClass.getInterfaces());
}
specifiedInterfaces = advised.getProxiedInterfaces();
}
}
List<Class<?>> proxiedInterfaces = new ArrayList<>(specifiedInterfaces.length + 3);
for (Class<?> ifc : specifiedInterfaces) {
// Only non-sealed interfaces are actually eligible for JDK proxying (on JDK 17)
if (isSealedMethod == null || Boolean.FALSE.equals(ReflectionUtils.invokeMethod(isSealedMethod, ifc))) {
proxiedInterfaces.add(ifc);
}
}
if (!advised.isInterfaceProxied(SpringProxy.class)) {
proxiedInterfaces.add(SpringProxy.class);
}
if (!advised.isOpaque() && !advised.isInterfaceProxied(Advised.class)) {
proxiedInterfaces.add(Advised.class);
}
if (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)) {
proxiedInterfaces.add(DecoratingProxy.class);
}
return ClassUtils.toClassArray(proxiedInterfaces);
}
JdkDynamicAopProxy中的proxiedInterfaces是从Advised的interfaces中加工而来。加工步骤如下:
- 如果interfaces是空的,则分析目标类,如果目标类是接口,那么将目标类当做要实现的接口添加到proxiedInterfaces中,如果目标类是个代理或Lambda,则将目标类上的所有接口都添加到proxiedInterfaces
- 将SpringProxy添加到proxiedInterfaces
- 如果没有设置隐藏代理信息,则将Advised添加到proxiedInterfaces
Advised的interfaces从何而来?
- 用户可以使用ProxyFactory直接添加接口
- Spring对其中的bean创建代理时,会对bean的类型进行分析,从类型中分析而来。读者可以看AbstractAutoProxyCreator代码。
再看JdkDynamicAopProxy对InvocationHandler的实现方法:
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);
}
}
}
可以看到:
- 如果代理的目标类没有自己实现
equals()、hashcode()方法,则直接调用Spring为代理类提供的equals和hashcode方法 - 如果调用的是DecoratingProxy中的
getDecoratedClass()和Advised接口中定义的方法,则调用Spring提供的方法。 - 如果不是以上两种,则通过Adivsed构造出应用到目标方法的过滤器链(MethodInteceptor数组),使用MehtodInvocation应用到方法上。
- MehtodInvocation是一个典型的责任链,每一个MethodInteceptor方法的
invoke调用完之后再执行下一个。
以上重点是搞清楚步骤3中如何构造出过滤器链,以及步骤4中过滤器链的应用过程。
我们看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;
}
AdvisedSupport中的代码只是实现了缓存作用,真正的构造逻辑在advisorChainFactory中:
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) {
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) {
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.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;
}
该方法的基本逻辑是根据Advised中Adivsor信息获取Advice和Pointcut(如果是PointcutAdvisor的话),如果Pointcut匹配当前正在调用的方法,则将Advice转化为MethodInceptor加入到拦截器链。具体的Piontcut匹配这里不在详说。Advice到MethodIntceptor的转化则是使用AdvisorAdaptor实现的。
拦截器链的执行过程如下图:

浙公网安备 33010602011771号