上一篇文章介绍了Spring AOP的JDK动态代理的过程,这一篇文章就要介绍下Spring AOP的Cglib代理过程,仍然是使用上一篇文章的工程案例。
JDK动态代理是由JdkDynamicAopProxy来生成代理对象的,Cglib则是由CglibAopProxy来生成代理对象的。JdkDynamicAopProxy、CglibAopProxy实现了AopProxy接口,如下:
然后详细看下CglibProxy的代理对象的生成过程。CglibProxy、JdkDynamicAopProxy都拥有一个非常重要的属性AdvisedSupport advised这个属性包含了拦截的配置信息,这个属性在JdkDynamicAopProxy中已经说过了,不再详细说明。
上述内容,就是使用Enhancer设置下要继承的父类、设置下要实现的接口、设置下回调然后就创建出代理对象。其中的一个重要的回调Callback为DynamicAdvisedInterceptor,在DynamicAdvisedInterceptor的intercept方法里面实现了和JDK动态代理同样类似的逻辑。
接下来我们看下这一拦截过程是如何实现的。在DynamicAdvisedInterceptor的intercept方法里:
上面和JDK动态代理一样也是分两大步,第一步获取一个拦截器链,第二步创建一个MethodInvocation来执行这个拦截器链。
第一步:和JDK动态代理获取拦截器链的过程一样的。
第二步:它创建的MethodInvocation是CglibMethodInvocation,它是继承了JDK动态代理所创建的ReflectiveMethodInvocation,覆写了ReflectiveMethodInvocation的invokeJoinpoint方法。ReflectiveMethodInvocation的invokeJoinpoint方法内容如下:
就是利用反射进行目标方法的调用执行。
再看下CglibMethodInvocation的invokeJoinpoint方法:
this.publicMethod就是说明所调用的方法是否是public类型的。我们来看下它的来历:
在构建CglibMethodInvocation这个MethodInvocation时进行赋值的。Modifier.isPublic(method.getModifiers());就是判断该方法是否是public类型的。
CglibMethodInvocation与ReflectiveMethodInvocation仅仅在执行目标方法的时候有所不同,当目标方法是public方法时,ReflectiveMethodInvocation一直采用反射的策略执行目标方法。而CglibMethodInvocation却使用this.methodProxy.invoke(this.target, this.arguments)代理方法来执行。看下它的好处的描述(CglibMethodInvocation的invokeJoinpoint()方法的注释):
当执行public方法时,会比反射有一个更好的性能。然而当我们在使用cglib的callback的时候却还是使用反射,没有去使用MethodProxy。因此我们还是按照源码的使用方式来使用,来提升性能。
本文章中许多步骤省略了,是因为在上一篇SpringAOP JDK的动态代理文章中都进行了详细介绍,同时许多的接口也在上上一篇文章SpringAOP的接口说明中给出了详细的说明。
JDK动态代理是由JdkDynamicAopProxy来生成代理对象的,Cglib则是由CglibAopProxy来生成代理对象的。JdkDynamicAopProxy、CglibAopProxy实现了AopProxy接口,如下:
1
2
3
4
5
6
7
|
public
interface
AopProxy {
Object getProxy();
Object getProxy(ClassLoader classLoader);
}
|
然后详细看下CglibProxy的代理对象的生成过程。CglibProxy、JdkDynamicAopProxy都拥有一个非常重要的属性AdvisedSupport advised这个属性包含了拦截的配置信息,这个属性在JdkDynamicAopProxy中已经说过了,不再详细说明。
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
public
Object getProxy(ClassLoader classLoader) {
if
(logger.isDebugEnabled()) {
logger.debug(
"Creating CGLIB proxy: target source is "
+
this
.advised.getTargetSource());
}
try
{
//此时的rootClass为BServiceImpl
Class<?> rootClass =
this
.advised.getTargetClass();
Assert.state(rootClass !=
null
,
"Target class must be available for creating a CGLIB proxy"
);
Class<?> proxySuperClass = rootClass;
//这里判断rootClass是否是Cglib代理所产生的类(内部判断rootClass的className是否包含$$),对于本工程肯定不符合,跳过
if
(ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for
(Class<?> additionalInterface : additionalInterfaces) {
this
.advised.addInterface(additionalInterface);
}
}
//验证proxySuperClass中的是否有final方法(仅仅是打印出来警告信息,不做任何处理)
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass);
// 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
UndeclaredThrowableStrategy(UndeclaredThrowableException.
class
));
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);
}
//略
}
|
上述内容,就是使用Enhancer设置下要继承的父类、设置下要实现的接口、设置下回调然后就创建出代理对象。其中的一个重要的回调Callback为DynamicAdvisedInterceptor,在DynamicAdvisedInterceptor的intercept方法里面实现了和JDK动态代理同样类似的逻辑。
接下来我们看下这一拦截过程是如何实现的。在DynamicAdvisedInterceptor的intercept方法里:
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
@Override
public
Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
throws
Throwable {
Object oldProxy =
null
;
boolean
setProxyContext =
false
;
Class<?> targetClass =
null
;
Object target =
null
;
try
{
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 = getTarget();
if
(target !=
null
) {
targetClass = target.getClass();
}
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() && Modifier.isPublic(method.getModifiers())) {
// 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 = methodProxy.invoke(target, args);
}
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
) {
releaseTarget(target);
}
if
(setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
|
上面和JDK动态代理一样也是分两大步,第一步获取一个拦截器链,第二步创建一个MethodInvocation来执行这个拦截器链。
第一步:和JDK动态代理获取拦截器链的过程一样的。
第二步:它创建的MethodInvocation是CglibMethodInvocation,它是继承了JDK动态代理所创建的ReflectiveMethodInvocation,覆写了ReflectiveMethodInvocation的invokeJoinpoint方法。ReflectiveMethodInvocation的invokeJoinpoint方法内容如下:
1
2
3
|
protected
Object invokeJoinpoint()
throws
Throwable {
return
AopUtils.invokeJoinpointUsingReflection(
this
.target,
this
.method,
this
.arguments);
}
|
就是利用反射进行目标方法的调用执行。
再看下CglibMethodInvocation的invokeJoinpoint方法:
1
2
3
4
5
6
7
8
|
protected
Object invokeJoinpoint()
throws
Throwable {
if
(
this
.publicMethod) {
return
this
.methodProxy.invoke(
this
.target,
this
.arguments);
}
else
{
return
super
.invokeJoinpoint();
}
}
|
this.publicMethod就是说明所调用的方法是否是public类型的。我们来看下它的来历:
1
2
3
4
5
6
|
public
CglibMethodInvocation(Object proxy, Object target, Method method, Object[] arguments,
Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
super
(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
this
.methodProxy = methodProxy;
this
.publicMethod = Modifier.isPublic(method.getModifiers());
}
|
在构建CglibMethodInvocation这个MethodInvocation时进行赋值的。Modifier.isPublic(method.getModifiers());就是判断该方法是否是public类型的。
CglibMethodInvocation与ReflectiveMethodInvocation仅仅在执行目标方法的时候有所不同,当目标方法是public方法时,ReflectiveMethodInvocation一直采用反射的策略执行目标方法。而CglibMethodInvocation却使用this.methodProxy.invoke(this.target, this.arguments)代理方法来执行。看下它的好处的描述(CglibMethodInvocation的invokeJoinpoint()方法的注释):
1
2
3
4
5
6
7
8
|
/**
* Gives a marginal performance improvement versus using reflection to
* invoke the target when invoking public methods.
*/
@Override
protected
Object invokeJoinpoint()
throws
Throwable {
//略
}
|
当执行public方法时,会比反射有一个更好的性能。然而当我们在使用cglib的callback的时候却还是使用反射,没有去使用MethodProxy。因此我们还是按照源码的使用方式来使用,来提升性能。
本文章中许多步骤省略了,是因为在上一篇SpringAOP JDK的动态代理文章中都进行了详细介绍,同时许多的接口也在上上一篇文章SpringAOP的接口说明中给出了详细的说明。