Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理
IOC容器的bean对象创建在之前的文章中已经分析过IOC容器的bean对象的创建过程,具体在:Spring IOC源码分析(七):IOC容器的设计实现与bean对象的创建流程,其中核心方法为AbstractAutowireCapableBeanFactory的createBean:首先检查是否创建了代理bean对象,如果创建了bean对象则直接返回;否则进入正常bean对象的创建流程,具...
IOC容器的bean对象创建
-
在之前的文章中已经分析过IOC容器的bean对象的创建过程,具体在:Spring IOC源码分析(七):IOC容器的设计实现与bean对象的创建流程
,其中核心方法为AbstractAutowireCapableBeanFactory的createBean:首先检查是否创建了bean的代理对象,如果创建了bean的代理对象则直接返回;否则进入正常bean对象的创建流程,具体在doCreateBean方法定义。// 代理bean对象创建 try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. // 调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation // (如果创建了bean,则还要调用BeanPostProcessor的postProcessAfterInitialization) // 调用用于生成AOP的代理对象的BeanPostProcessor,如果bean不为null,则说明产生代理对象了,可以直接返回 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { // 如果bean不为null ,则直接返回,这种情况通常为AOP创建了代理对象。后面的doCreateBean不再执行 return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } // 正常bean对象创建 try { // 正常的,非代理bean对象的创建 // 包括检查是否进行了类加载(没有则进行类加载),bean对象实例创建,bean对象实例的属性赋值,init-method的调用,BeanPostProcessor的调用 Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; }
-
由以上代码分析可知,代理对象的创建是在resolveBeforeInstantiation方法定义的:首先调用applyBeanPostProcessorsBeforeInstantiation方法来创建代理对象,如果创建成果,即bean不为空,则调用applyBeanPostProcessorsAfterInitialization方法来调用BeanPostProcessor的postProcessAfterInitialization方法,因为如果创建了代理对象,该方法返回后就直接返回该代理对象bean了,不再进行往下执行,故在这里调用BeanPostProcessor的postProcessAfterInitialization执行后置处理。
/** * Apply before-instantiation post-processors, resolving whether there is a * before-instantiation shortcut for the specified bean. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return the shortcut-determined bean instance, or {@code null} if none */ @Nullable protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { // instantiation // 调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation // 如果返回不是null,则一般是AOP的代理对象 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { // 如果使用postProcessBeforeInstantiation创建了bean对象,则是当前bean对象的代理对象了 // 这个方法执行完,退出则直接返回该代理bean对象了, // 故在这里调用一下其他BeanPostProcessor的postProcessAfterInitialization // initialization // 调用普通BeanPostProcessor的postProcessAfterInitialization bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }
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); } ... } ... }
更多推荐
所有评论(0)