前言
前面两部分讲了程序入口 和 切面和增强的取得。这一部分讲解代理的创建。
正文
查找Advisor的getAdvicesAndAdvisorsForBean方法的实现方式已经介绍完了,接下来我们介绍一下生成代理的createProxy方法的实现方式。在这个方法里重要的方法如下:
- buildAdvisors:创建切面(todo:在找出适合的Advisor时,取得的结果可能是Advice吗)
- getProxy:取得代理(也是创建代理过程)
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 设置ProxyTargetClass属性。
// 如果ProxyTargetClass为True,使用CGLIB方式代理;False,使用JdkDynamicProxy方式
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 创建切面
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 把创建的切面添加到ProxyFactory里
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 创建代理
return proxyFactory.getProxy(getProxyClassLoader());
}
1,创建切面流程
在buildAdvisors方法中,比较重要的是advisorAdapterRegistry.wrap方法的调用,这个方法是把Advice包装成一个Advisor。
protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) {
// Handle prototypes correctly...
// 通过interceptorNames属性,获得声明式代理方式下,指定的interceptorNames属性里声明的advice或者advisor
// 在AspectJ代理方式时,应该没有使用(因为感觉没发现地方指定interceptorNames属性)
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<Object>();
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors != null) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isDebugEnabled()) {
int nrOfCommonInterceptors = (commonInterceptors != null ? commonInterceptors.length : 0);
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
// 通过AdvisorAdapter把allInterceptors里的元素包装成Advisor。
// allInterceptors里的元素不一定是Advisor类型,可能是Advice
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
wrap方法是,如果参数是Advice类型,就包装成Advisor。包装时候是使用DefaultPointcutAdvisor进行包装的。
包装时候使用的是AdvisorAdapter接口。这个接口有两个方法:
- supportsAdvice(Advice advice):判断参数的Advice是不是当前Adapter支持的Advice。
- getInterceptor(Advisor advisor):根据参数Advice生成Interceptor。
supportsAdvice
方法里使用的adapters属性在DefaultAdvisorAdapterRegistry的构造函数里就进行赋值了,设置了3个Adapter:
- MethodBeforeAdviceAdapter
- AfterReturningAdviceAdapter
- ThrowsAdviceAdapter
这时在我们主要用到了supportsAdvice方法。这3个Adapter循环对Advice进行处理,如果Advice是Adapter支持的类型,就返回一个Advisor。
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
// 如果Advice是已经实现了MethodInterceptor接口的实例,就不用包装了,
// 因为我们最终要生成的是Interceptor,现在包装成Advisor只是一个过程。
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
// 循环对Advice进行判断,如果是支持类型,就返回包装后的Advisor
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
2 创建代理相关流程
buildAdvisors
方法及其子方法介绍完了,我们最后来介绍最proxyFactory.getProxy(getProxyClassLoader())
方法的实现过程。
前在的一切都是准备资源,这个方法是利用资源生成代理的实现。我们先来看一看getProxy
方法的内容。
这个方法里只有行代码createAopProxy().getProxy(classLoader)
。这行代码中,首先调用了createAopProxy
这个方法,
在createAopProxy
方法里又调用了getAopProxyFactory().createAopProxy(this)
方法。
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
我们看一下createAopProxy方法的具体内容。这个方法的实现是在DefaultAopProxyFactory类中。
这个方法的主要功能是,根据optimize、ProxyTargetClass等参数来决定生成Jdk动态代理,还是生成Cglib代理。
@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.");
}
if (targetClass.isInterface()) {
// 生成Jdk动态代理
return new JdkDynamicAopProxy(config);
}
// 成生Cglib代理
return new ObjenesisCglibAopProxy(config);
}
else {
// 生成Jdk动态代理
return new JdkDynamicAopProxy(config);
}
Jdk动态代理和Cglib代理的区别和实现方式在这里就不具体讲解了,请大家上网找一些资料。
Spring对这两种代理做了包装,包装类分别是:
- JdkDynamicAopProxy
- ObjenesisCglibAopProxy类。
这两个类的构造函数是AdvisedSupport,这个类保包含了 Spring AOP的配置和对配置的一些访问方法(例如:Advisor),还有AdvisorChainFactory对象。AdvisorChainFactory对象的功能主要是,根据在前面找到的合适的Advisor成生Interceptor,最后代理调用时实际上都是调用的Interceptor。
createAopProxy方法讲完后,createAopProxy后面调用getProxy方法。这个方法不算难,主要是根据要生成代理的类型(Jdk动态代理和Cglib),把这两种技术各自独特的实现代理的过程给封装了。比较复杂的逻辑是在,代理被调用时回调方法里面。在回调方法里面,及到了Intercceptor链(Interceptor包装了Advisor)的调用,这个实现也挺巧妙的。
我们拿Jdk动态代理的回调来说明。了解Jdk动态代理的话都会知道,在实现Jdk动态代理功能,要实现InvocationHandler接口的invoke方法(这个方法是一个回调方法)。
被代理类中的方法被调用时,实际上是调用的invoke方法,我们看一看这个方法的实现。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
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;
}
// May be null. Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// Get the interception chain for this method.
// 利用Adivsor,生成一个我们之前定义的Advice调用链。在调用被代理方法前后时,调用这个链。
// 在这个方法里面,实际上调用advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice方法来实现了,
// 这个方法的作用我们在上面已经说过了,在这里不再重复了。
// 这里生成的链的对象全部都封装成了MethodInterceptor。
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.
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
}
else {
// We need to create a method invocation...
// 这里非常重要。生成一个方法调用的控制类,并调用proceed方法,进行链和被代理方法的调用
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.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);
}
}
}
上面的方法里使用了ReflectiveMethodInvocation类,进行链和被代理方法的调用的控制。那么它到底是怎么进行控制的呢?
下面是ReflectiveMethodInvocation类Proceed方法:
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 首先,判断是不是所有的interceptor(也可以想像成advisor)都被执行完了。
// 判断的方法是看currentInterceptorIndex这个变量的值,增加到Interceptor总个数这个数值没有,
// 如果到了,就执行被代理方法(invokeJoinpoint());如果没到,就继续执行Interceptor。
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 如果Interceptor没有被全部执行完,就取出要执行的Interceptor,并执行。
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 如果Interceptor是PointCut类型
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
// 如果当前方法符合Interceptor的PointCut限制,就执行Interceptor
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
// 如果不符合,就跳过当前Interceptor,执行下一个Interceptor
// 这里是递归执行proceed方法,currentInterceptorIndex的值一直在增加
// 当currentInterceptorIndex值达到了方法最大的界限的话,就会从递归最里层的proceed方法一层层返回来。
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
// 如果Interceptor不是PointCut类型,就直接执行Interceptor里面的增强。
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);
}
}
看完上面的代码,思考一下,可能会有两个问题。
1,我们定义增加时,可以定义很多种,比如前置增加BeforeAdvice,后置增强等。在这个方法里只看到了调用Interceptor(也就是Advisor),是在哪里控制这些增强的调用顺序的呢?比如,先调用前置增强,再调用被代理方法,再调用后置增强等。
2,增强调用完后,是如何调用下一个增强的呢?上面的代码中,调用完增强后,就返回了。
上面问题的答案可以在MethodInterceptor的实现类里找到,我们拿MethodBeforeAdviceInterceptor为例子。
从下面代码可以看出来,当invoke方法被调用时,首先调用的是前置增强,然后再调用MethodInvocation的proceed方法,也就是我们上面介绍的proceed方法。这个MethodInvocation的引用,就是在ReflectiveMethodInvocation调用interceptor时,把自己传了过来。在Interceptor里调用proceed方法的意思是告诉MethodInvocation,我(增强)执行完了,你继续吧
,接下来是继续执行其它增强,还是执行被代理方法,就由上面的ReflectiveMethodInvocation逻辑判断了。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private 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();
}
}
AfterReturningAdviceInterceptor的invoke方法代码如下:
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
假设一共有两个Interceptor
1, Interceptor1:前置增强
2, Interceptor2:后置增强
- 1, ReflectiveMethodInvocation:判断Interceptor没执行完,执行Interceptor1
- 2, Inerceptor1:执行前置增强,然后执行MethodInvocation的proceed方法。
- 3, ReflectiveMethodInvocation:判断Interceptor没执行完,执行Interceptor2
- 4, Interceptor2:执行MethodInvocation的proceed方法(后置增强还没有执行)
- 5, ReflectiveMethodInvocation:判断所有Interceptor都执行完了,执行目标方法。目标方法执行完后,回到Interceptor2调用proceed方法的地方。
- 6, Interceptor2:调用proceed返回后,继续调用后面的后置增强。后置增强执行完后,回到MethodInvocation调用Interceptor2的地方
- 7, ReflectiveMethodInvocation:调用Interceptor2完成返回后,因为没有其它(Intercetpor或目标方法)要执行,所以回到Interceptor1调用proceed方法的地方
- 8, Interceptor1:调用的proceed方法返回后,因为没有其它要执行的了,所以回到MethodInvocation调用Interceptor1的地方
- 9, ReflectiveMethodInvocation:调用Interceptor1完成返回后,因为没有其它(Intercetpor或目标方法)要执行,所以回到最初调用proceed方法的地方
ReflectiveMethodInvocation判断还有Interceptor没执行完,执行Interceptor1
Interceptor1执行完后,告诉ReflectiveMethodInvocation“我执行完了”,你继续吧
ReflectiveMethodInvocation判断还有Interceptor没执行完,执行Interceptor2
Interceptor2执行完后,告诉ReflectiveMethodInvocation“我执行完了”,你继续吧
ReflectiveMethodInvocation判断Interceptor都执行完了,执行代理方法
回到Interceptor2调用执行完后,告诉ReflectiveMethodInvocation“我执行完了”,你继续吧
在这种结构的控制下,不管在proceed里调用Interceptor里面的逻辑是前置增强处理,还是后置增强处理,都可以达到:
所有前置增强执行 -> 被代理方法执行 -> 所有的后置增强执行
的调用顺序,所以这个设置还是挺巧妙的。
这种设计还有一个好处,因为这种设计把前置后置增强的调用顺序控制,放到了各个增强用的Interceptor里了,没有放到proceed方法里,所以当有新的增强类型出来的话,把调用顺序控制放到新的增强的Interceptor里就好了,不用修改现有的类,例如proceed方法。
为什么执行代理Chain的时候,每个Chain里的元素都要是MethodInterceptor类型的呢?
因为“Aop联盟”定义了一套AOP的接口,而且还定义的接口的调用规则,而且还起草了AOP的一些组件和运作方式。
比如,定义了Interceptor Framework,Reflection,Metadata Handling(应该是注解处理),Class Loading Framework等。
拿我们遇到的接口举例:
- Joinpoint:定义了proceed()等方法,proceed这个方法的作用是调用下一个interceptor。
- MethodInterceptor:定义了invoke(MethodInvocation invocation)方法。
- MethodInvocation:实现了Joinpoint接口。根据定义来说,这个接口是一个“jointpoint(就是被拦截的方法/对象)”,什么样的JointPoint呢?
可以被拦截到的JointPoint。
看Spring的代码,被拦截方法的调用和Interceptor Chain的调用都是在这里控制的。所以可以看出Joinpoint接口是定义Advice,MethodInvocation接口是定义执行Advice的接口。在MethodInterceptor的Javadoc里还写了下面的说明和用例:
The user should implement the invoke(MethodInvocation) method to modify the original behavior. E.g. the following class implements a tracing interceptor (traces all the calls on the intercepted method(s)):
用户需要实现 invoke(MethodInvocation) 方法来修改原来的行为。例如,下面类实现了一个tracing interceptor。
class TracingInterceptor implements MethodInterceptor {
Object invoke(MethodInvocation i) throws Throwable {
System.out.println("method "+i.getMethod()+" is called on "+
i.getThis()+" with args "+i.getArguments());
Object ret=i.proceed();
System.out.println("method "+i.getMethod()+" returns "+ret);
return ret;
}
}
看了一上面的代码,是不是和上面说的MethodBeforeAdviceInterceptor还有AfterReturningAdviceInterceptor的实现方式几乎一样。这样应该就可以理解Spring为什么要这么做了吧。
Aop联盟的接口Javadoc如下,有兴趣的可以看看。
http://aopalliance.sourceforge.net/doc/index.html