Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理

AOP代理对象的创建

AOP相关的代理对象的创建主要在applyBeanPostProcessorsBeforeInstantiation方法实现:

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) { // 查找实现了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor
// 其中在spring-aop模块定义的AspectJAwareAdvisorAutoProxyCreator就实现了InstantiationAwareBeanPostProcessor接口
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 调用postProcessBeforeInstantiation方法创建对象result
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); // 如果创建成功则直接返回
if (result != null) {
return result;
}
}
}
return null;
}
核心实现为:获取所有的BeanPostProcessor,然后遍历查看是否为子接口InstantiationAwareBeanPostProcessor,如果是则调用其postProcessBeforeInstantiation方法。
AOP代理对象创建器:AspectJAwareAdvisorAutoProxyCreator
InstantiationAwareBeanPostProcessor接口是BeanPostProcessor接口的子接口,主要作用如下英文所示:即主要用于为特殊定制目标bean的实例化过程,如给目标对象创建代理对象。
Typically used to suppress default instantiation for specific target beans,
for example to create proxies with special TargetSources (pooling targets,
lazily initializing targets, etc), or to implement additional injection strategies
such as field injection. This interface is a special purpose interface, mainly for internal use within the framework
在spring-aop的配置解析的分析可知:Spring AOP源码分析(二):AOP的三种配置方式与内部解析实现
,在解析spring的XML配置文件applicationContext.xml的aop:config或aop:aspect-autoproxy标签时,会创建并注册AspectJAwareAdvisorAutoProxyCreator(aop:aspect-autoproxy对应的AnnotationAwareAspectJAutoProxyCreator为AspectJAwareAdvisorAutoProxyCreator子类)这个BeanPostProcessor到spring容器。
AspectJAwareAdvisorAutoProxyCreator的类继承体系结构中,实现了InstantiationAwareBeanPostProcessor接口,具体为在抽象父类AbstractAutoProxyCreator:同时定义了postProcessBeforeInstantiation方法的实现。
// 提供为给定的bean对象创建对应的代理对象的方法实现
// 同时提供代理对象需要的方法拦截器的创建,其中拦截器包括所有代理对象公用的拦截器和某个代理对象私有的拦截器
@SuppressWarnings("serial")
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware { ... // 在bean对象实例的创建过程中,在创建bean对象实例之前,先调用这个方法,看是否需要创建一个AOP代理对象直接返回
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName); // 返回null,则表示不是AOP的目标对象,不需要创建代理对象
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
} // Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
} // specificInterceptors类型为Advisor[],是当前bean需要的辅助功能列表
// 因为Advisor集成了pointcut和advice,故可以知道当前bean是否在pointcut拦截范围内,
// 如果在获取配置对应的advice列表,该列表作为代理对象的interceptor方法拦截器
// getAdvicesAndAdvisorsForBean由子类实现
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); // 基于以上辅助功能列表,创建该bean对应的代理对象proxy
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass()); // 只有创建了proxy,才不返回null
return proxy;
} return null;
} ... }
postProcessBeforeInstantiation方法的核心逻辑为:通过在spring-aop配置解析时创建的advisors来为该目标bean查找对应的辅助方法advices,其中advisor为集成了pointcut和advice。这些辅助方法advices作为代理对象的方法拦截器列表specificInterceptors,即代理对象拦截目标对象的方法执行,然后在方法执行前后可以执行该方法拦截器列表对应的方法,从而为目标对象的方法添加这些辅助功能。
创建代理对象:createProxy
createProxy的定义如下:代理对象可以基于JDK的动态代理或者基于CGLIB来创建,其中默认为基于JDK的动态代理,如果aop:config的proxy-target-class属性为true或者目标类没有实现接口,则使用CGLIB来创建代理对象。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
} // 每个bean对象都使用一个单例的ProxyFactory来创建代理对象,因为每个bean需要的辅助方法不一样,
// 然后将该ProxyFactory对象引用作为构造函数参数创建对应的代理对象
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this); // 检查是否配置了<aop:config />节点的proxy-target-class属性为true
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
} Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); // 为该代理工厂添加辅助功能包装器Advisors,结合Advisors来生成代理对象的方法拦截器
proxyFactory.addAdvisors(advisors); // 目标类
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
} // 为目标类创建代理对象,如果配置了aop:config的proxy-target-class为true,则使用CGLIB
// 否则如果目标类为接口则使用JDK代理,否则使用CGLIB
return proxyFactory.getProxy(getProxyClassLoader());
}
JDK动态代理
基于接口实现,通过实现目标类所包含的接口的方法来实现代理,即返回的代理对象为接口的实现类。由于是基于JDK的动态代理实现,即实现了JDK提供的InvocationHandler接口,故在运行时在invoke方法拦截目标类对应被代理的接口的所有方法的执行:获取当前执行的方法对应的方法拦截器链,然后通过反射执行该方法时,在方法执行前后执行对应的方法拦截器。
// JDK的动态代理是基于接口的,故只能代理接口中定义的方法。
// 该类需要通过代理工厂,具体为继承了AdvisedSupport的代理工厂来创建,而不是直接创建,
// 因为AdvisedSupport提供了AOP的相关配置信息,如Advisors列表等。
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable { ... public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource;
Object target = null; try { ... 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); // 获取该方法对应的方法拦截器列表
// 实现:通过该方法所在类对应的Advisors,获取该方法的辅助功能Advices列表,即方法拦截器列表。这里的实现为懒加载,
// 即当方法第一次调用的时候才创建该方法拦截器列表,然后使用一个ConcurrentHashMap缓存起来,之后的方法调用直接使用。 // 其中advised就是该方法的所在bean对应的ProxyFactory对象引用,通过ProxyFactory来创建AopProxy,即当前类对象实例。 // 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 {
// 如果当前方法包括方法拦截器,即在执行时需要其他额外的辅助功能,则创建ReflectiveMethodInvocation
// We need to create a method invocation...
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;
}
...
} ... }
CGLIB代理
  • 创建目标类的子类来实现代理,代理拦截的只能是目标类的public和protected方法。核心方法为getProxy即创建代理对象,在这里织入了辅助功能。

// 基于类的代理,具体实现为通过创建目标类的子类来实现代理,即代理对象对应的类为目标类的子类。
// 所以目标类的需要被代理的方法不能为final,因为子类无法重写final的方法;同时被代理的方法需要是public或者protected,不能是static,private或者包可见,即不加可见修饰符。
// 如在事务中,@Transactional注解不能对private,static,final,包可见的方法添加事务功能,只能为public方法。
// 这个代理对象也需要通过代理工厂来创建,具体为继承了AdvisedSupport的代理工厂来创建,而不是直接创建。
@SuppressWarnings("serial")
class CglibAopProxy implements AopProxy, Serializable { ... // 创建代理对象
public Object getProxy(@Nullable ClassLoader classLoader) { ... Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
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); // 创建目标类的子类来实现代理,即织入辅助功能
// 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 ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); 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);
} ... } ... }

获取更多学习资料,可以加群:473984645或扫描下方二维码

Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理

上一篇:android gridview按钮边框和定制点击颜色


下一篇:火焰图分析openresty性能瓶颈