前言
前面分析了spring创建代理的过程,spring的代理又可以分为JDK动态代理喝CGLIB代理。这篇博文主要分析CGLIB代理,围绕CglibAopProxy展开。
程序入口
DefaultAopProxyFactory#createAopProxy方法中使用 new ObjenesisCglibAopProxy的方式创建代理。
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 根据这三个条件 决定使用JDK动态代理 还是CGLIB代理
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() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
继承关系
由继承关系图可知,CGLIB代理主要还是由CglibAopProxy完成。
public ObjenesisCglibAopProxy(AdvisedSupport config) {
super(config);
}
public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}
获取代理对象
CglibAoProxy也实现AopProxy方法,从其getProxy方法入手,进行分析。
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
// CGLIB是通过生成被代理的子类 完成动态代理的
// 首先获取被代理的类
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
// 添加代理类实现的接口,这里会去重
this.advised.addInterface(additionalInterface);
}
}
// 验证类,根据需要编写日志消息。
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// 创建并配置 Enhancer
// 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));
// CGLIB命名策略
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// 代理类字节码的默认生成策略
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
// 获取生成代理需要callBak
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// 在上面的 getCallbacks 调用之后,fixedInterceptorMap 仅在此时填充
// 一个method只能被一个callback增强
// 使用CallbackFilter封装,其作用是决定这个method由哪个callback处理。
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);
}
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) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
这个方法内通过getCallBack方法来设置拦截器链。
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// 将拦截器封装在DynamicAdvisedInterceptor中
// Choose an "aop" interceptor (used for AOP calls).
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
// targetInterceptor 直接在intercept中调用目标对象的目标方法
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
Callback[] mainCallbacks = new Callback[] {
// 普通增强,将拦截器加入到callback中
aopInterceptor, // for normal advice
// 直接调用
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
// equals方法专用拦截器
new EqualsInterceptor(this.advised),
// hashCode方法专用拦截器
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimizations by sending the AOP calls
// direct to the target using the fixed chain for that method.
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(method, x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
对方法进行增强
在为Enhancer设置拦截器链时,封装了ProxyCallbackFilter,它实现了CallBackFilter接口,重点关注实现的accept方法。在这个方法内决定使用哪一个Callback来进行增强。
@Override
public int accept(Method method) {
// finalizeMethod 不需要重写
if (AopUtils.isFinalizeMethod(method)) {
logger.trace("Found finalize() method - using NO_OVERRIDE");
return NO_OVERRIDE;
}
// Advised由AdvisedDispatcher处理
if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
if (logger.isTraceEnabled()) {
logger.trace("Method is declared on Advised interface: " + method);
}
return DISPATCH_ADVISED;
}
// equals方法处理
// We must always proxy equals, to direct calls to this.
if (AopUtils.isEqualsMethod(method)) {
if (logger.isTraceEnabled()) {
logger.trace("Found 'equals' method: " + method);
}
return INVOKE_EQUALS;
}
// hashCode方法处理
// We must always calculate hashCode based on the proxy.
if (AopUtils.isHashCodeMethod(method)) {
if (logger.isTraceEnabled()) {
logger.trace("Found 'hashCode' method: " + method);
}
return INVOKE_HASHCODE;
}
Class<?> targetClass = this.advised.getTargetClass();
// Proxy is not yet available, but that shouldn't matter.
List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
boolean haveAdvice = !chain.isEmpty();
boolean exposeProxy = this.advised.isExposeProxy();
boolean isStatic = this.advised.getTargetSource().isStatic();
boolean isFrozen = this.advised.isFrozen();
if (haveAdvice || !isFrozen) {
// If exposing the proxy, then AOP_PROXY must be used.
// 如果暴露代理,则必须使用 AOP_PROXY。
if (exposeProxy) {
if (logger.isTraceEnabled()) {
logger.trace("Must expose proxy on advised method: " + method);
}
return AOP_PROXY;
}
// Check to see if we have fixed interceptor to serve this method.
// Else use the AOP_PROXY.
// 是否由固体的拦截器处理当前方法
if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(method)) {
if (logger.isTraceEnabled()) {
logger.trace("Method has advice and optimizations are enabled: " + method);
}
// We know that we are optimizing so we can use the FixedStaticChainInterceptors.
int index = this.fixedInterceptorMap.get(method);
return (index + this.fixedInterceptorOffset);
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Unable to apply any optimizations to advised method: " + method);
}
// 否则使用AOP_PROXY 也就是 DynamicAdvisedInterceptor
return AOP_PROXY;
}
}
else {
// See if the return type of the method is outside the class hierarchy of the target type.
// If so we know it never needs to have return type massage and can use a dispatcher.
// If the proxy is being exposed, then must use the interceptor the correct one is already
// configured. If the target is not static, then we cannot use a dispatcher because the
// target needs to be explicitly released after the invocation.
if (exposeProxy || !isStatic) {
// 如果需要暴露代理对象,或者target是可变的,
// 通过 StaticUnadvisedExposedInterceptor 代理
return INVOKE_TARGET;
}
Class<?> returnType = method.getReturnType();
if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
if (logger.isTraceEnabled()) {
logger.trace("Method return type is assignable from target type and " +
"may therefore return 'this' - using INVOKE_TARGET: " + method);
}
// 当前方法返回类型是目标对象的类型
// 通过 StaticUnadvisedExposedInterceptor 代理
return INVOKE_TARGET;
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Method return type ensures 'this' cannot be returned - " +
"using DISPATCH_TARGET: " + method);
}
// 否则使用 StaticDispatcher
return DISPATCH_TARGET;
}
}
}
使用CGLIB代理,需要实现MethodInterceptor接口,实现intercept方法。在getCallback可以看到实际上是拦截器封装为DynamicAdvisedInterceptor,
在ProxyCallbackFilter中也提到使用AOP_PROXY实际上就是DynamicAdvisedInterceptor。DynamicAdvisedInterceptor实现了MethodInterceotor方法,主要看一下它的intercept方法。
@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) {
// Make invocation available if necessary.
// 需要在拦截器暴露代理对象,把代理对象添加到 ThreadLocal<Object> currentProxy
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);
// 当前方法的拦截器链
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() && CglibMethodInvocation.isMethodProxyCompatible(method)) {
// 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);
try {
// 拦截器为空,则不需要增强,直接调用这个方法。
retVal = methodProxy.invoke(target, argsToUse);
}
catch (CodeGenerationException ex) {
CglibMethodInvocation.logFastClassGenerationFailure(method);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
}
else {
// 存在拦截器,创建CglibMethodInvocation,管理拦截器链
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
// 通过 process 进行拦截器链的调用
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
用于管理拦截器链的CglibMethodInvocation类继承自ReflectMethodInvocation,在分析JDK动态代理时已经解读过了,这里也并没有重写process方法。