AOP 代理实例的创建

警告
本文最后更新于 2020-12-01,文中内容可能已过时。

spring源码系列文章,示例代码的中文注释,均是 copy 自 https://gitee.com/wlizhi/spring-framework

链接中源码是作者从 github 下载,并以自身理解对核心流程及主要节点做了详细的中文注释。


1 创建实例的流程

创建代理实例在 createProxy() 中进行。

createProxy() 中有两个比较关键的方法:

  1. buildAdvisors()
  2. getProxy()

源码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {
        // 省略...
		// 注意这个ProxyFactory,里面封装了 Advisors
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		// 省略...
		// TODO 重点:构建增强对象,这里会在原有的Advisor列表中,增加存在的MethodInterceptor
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		// TODO 重点:生成代理对象
		return proxyFactory.getProxy(getProxyClassLoader());
	}
}

2 构建Advisor - BuildAdvisors

来到 buildAdvisors() 源码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
		// Handle prototypes correctly...
		// 获取已有的方法拦截器,名称,并包装成Advisor
		Advisor[] commonInterceptors = resolveInterceptorNames();

		List<Object> allInterceptors = new ArrayList<>();
		if (specificInterceptors != null) {
			allInterceptors.addAll(Arrays.asList(specificInterceptors));
			if (commonInterceptors.length > 0) {
				if (this.applyCommonInterceptorsFirst) {
					allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
				}
				else {
					allInterceptors.addAll(Arrays.asList(commonInterceptors));
				}
			}
		}
        // 省略部分代码...
		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i++) {
			// 在这里进行构建的,最终,所有的通知方法都会封装成Advisor。
			// 实际上我们自己定义的切面,到这里时,都已经是Advisor了,没有做任何处理直接返回了。
			// 之所以在这里要再进行封装,是因为Spring中涉及过多的拦截器,增强器,增强方法等方式来对逻辑进行增强,
			// 有些情况allInterceptors中可能存在Advice对象,所以非常有必要统一封装成Advisor
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}
}

从源码中可以看出,首选获取了一个 Advisor 数组,然后与之前搜集好的 Advisor 数组进行合并。

对合并后的结果进行遍历,然后调用 advisorAdapterRegistry.wrap(),wrap() 方法的作用,源码注释中有详细说明。

简单看一下 resolveInterceptorNames() 的过程:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    private Advisor[] resolveInterceptorNames() {
		BeanFactory bf = this.beanFactory;
		ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
		List<Advisor> advisors = new ArrayList<>();
		// 这里会根据interceptorNames中存储的拦截器名称,获取到对应的bean实例,最终包装成Advisor,添加到列表中返回。
		for (String beanName : this.interceptorNames) {
			if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
				Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
				Object next = bf.getBean(beanName);
				advisors.add(this.advisorAdapterRegistry.wrap(next));
			}
		}
		return advisors.toArray(new Advisor[0]);
	}
}

代码流程是:首先对 interceptorNames 进行遍历,依次对其进行 getBean 操作,然后使用 advisorAdapterRegistry.wrap() 将其包装成 Advisor。

来到 advisorAdapterRegistry.wrap():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
		//如果要封装的对象本身就是Advisor类型的,无须做任何处理
		if (adviceObject instanceof Advisor) {
			return (Advisor) adviceObject;
		}
		//因为此封装只对Advisor和Advice两种类型的数据有效,如果不是将不能封装
		if (!(adviceObject instanceof Advice)) {
			throw new UnknownAdviceTypeException(adviceObject);
		}
		Advice advice = (Advice) adviceObject;
		if (advice instanceof MethodInterceptor) {
			//如果是MethodInterceptor类型则使用DefaultPointcutrAdvisor封装
			// So well-known it doesn't even need an adapter.
			return new DefaultPointcutAdvisor(advice);
		}
		// 如果存在Advisor类型的适配器那么也同样需要进行封装
		for (AdvisorAdapter adapter : this.adapters) {
			// Check that it is supported.
			// @Before,@After使用的DefaultPointcutAdvisor
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
		throw new UnknownAdviceTypeException(advice);
	}
}

上面源码逻辑比较简单:

  1. 首先判断传入的实例是否为 Advisor 实现类,如果为 true 不作任何处理,直接返回。
  2. 对 MethodInterceptor 的实例,包装成 DefaultPointcutAdvisor 返回。
  3. 循环成员 adapters 中预定义的所有 AdvisorAdapter,进行适配操作,如果有适配器支持这个 Advice,就包装成 DefaultPointcutAdvisor 返回。
  4. 如果以上条件都未处理成功,直接抛出异常。所以这里传入的对象一定得是一个 Advice 实现。

其实我们自定义的切面类中的通知增强,在这里都已经包装为 Advisor了,大多数都是走的直接返回。

关于成员变量 adapters,是在无参构造中初始化的:

1
2
3
4
5
6
7
8
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
    public DefaultAdvisorAdapterRegistry() {
		// 注册三种适配器。
		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
		registerAdvisorAdapter(new AfterReturningAdviceAdapter());
		registerAdvisorAdapter(new ThrowsAdviceAdapter());
	}
}

关于 MethodInterceptor、 Advice、 AdvisorAdapter暂且跳过。

3 生成代理实例 - GetProxy

getProxy() 中只有一行代码:

1
2
3
4
5
6
7
public class ProxyFactory extends ProxyCreatorSupport {

	public Object getProxy(@Nullable ClassLoader classLoader) {
		//根据目标对象是否有接口来判断采用什么代理方式,cglib代理还是jdk动态代理
		return createAopProxy().getProxy(classLoader);
	}
}

先看第一个方法 createAopProxy()。 步骤一(注意调用下一步方法的参数):

1
2
3
4
5
6
7
8
9
public class ProxyCreatorSupport extends AdvisedSupport {

    protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}
}

从上面代码看出,会调到另一个方法,注意这个参数,传入了一个 AdvisedSupport,里面封装了通知方法、切点等信息。 步骤二:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			// 如果目标类是一个接口,则使用JDK动态代理
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			// 使用cglib代理。
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}
}

从上面代码可以看出,将 AdvisedSupport 封装到了创建代理的对象中。

有两种情况,可能会使用 JDK 动态代理、或者使用 Cglib 子类代理。无论是xml方式还是注解方式配置,激活代理时都可以配置一个布尔类型的属性 proxyTargetClass,如果不配置,默认值是 false。这个属性的作用是:指明是否要创建基于子类(CGLIB)的代理,而不是基于Java标准接口的代理。

默认是使用 JDK 动态代理,如果配置了 proxyTargetClass=true,会默认使用 Cglib 子类代理,但如果被代理的类本身是接口的话,依然会使用JDK动态代理。

以上规律从上面的源码中可以看到,在两个 if 条件中判断的。


接着看 getProxy(),这里真正生成了代理对象,以 JDK 动态代理为例(cglib也类似,其实都是将 Advisor 的必要信息封装到一个类中,将执行行为封装到对应的回调函数中):

1
2
3
4
5
6
7
8
9
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

	public Object getProxy(@Nullable ClassLoader classLoader) {
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		// 创建代理对象,参数中的InvocationHandler传入的是this,那么本类中一定有invoke(),在调用代理类方法时,就会执行这个invoke()。
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}
}

源码中调用了 Proxy.newProxyInstance() 生成代理,这是典型的 JDK 动态代理的生成方式。

注意

仔细看 Proxy.newProxyInstance(classLoader, proxiedInterfaces, this),这里第三个传输是 this,那么这个 this 一定实现了 InvocationHandler 接口、并实现了 invoke()。

记一下 JdkDynamicAopProxy 的声明: final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable

可以看到 JdkDynamicAopProxy 实现了 InvocationHandler。

到这里,代理对象创建完成。

动态代理的入口方法 wrapIfNecessary() 到这里执行完成,会将创建的代理对象返回。将代码执行流程回转到 doCreateBean 中:

–> wrapIfNecessary()
–> postProcessAfterInitialization()
–> applyBeanPostProcessorsAfterInitialization()
–> applyBeanPostProcessorsAfterInitialization()
–> initializeBean()
–> exposedObject = initializeBean(beanName, exposedObject, mbd);

实际上,Spring对AOP的支持,这一整块儿,都是基于 BeanPostProcessor.applyBeanPostProcessorsAfterInitialization() 完成的。

冗长的流程,最终回转到 doCreateBean 中,在遍历 BeanPostProcessor 并依次调用 applyBeanPostProcessorsAfterInitialization() 时,传入创建好的bean实例,返回一个实例,而AbstractAutoProxyCreator中定义了骨架方法wrapIfNecessary(),这里面返回了一个代理实例,由此沿着调用链向上返回,最终getBean()得到的就可能是一个代理实例。

之所以说是可能,因为后面的流程,还有一个 getObjectForBeanInstance() 执行,如果 bean 是 FactoryBean 类型,会返回 getObject() 中返回的实例。文章 复杂对象的构建方式 - FactoryBean 中有详细说明。