Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal} for retrieval via the {@link org.springframework.aop.framework.AopContext} class. Off by default, i.e. no guarantees that {@code AopContext} access will work.
/** * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean * initialization callbacks (like InitializingBean's <code>afterPropertiesSet</code> * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet */ Object postProcessBeforeInitialization(Object bean, String beanName)throws BeansException; /** * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean * instance and the objects created by the FactoryBean (as of Spring 2.0). The * post-processor can decide whether to apply to either the FactoryBean or created * objects or both through corresponding {@code bean instanceof FactoryBean} checks. * <p>This callback will also be invoked after a short-circuiting triggered by a * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, * in contrast to all other BeanPostProcessor callbacks. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.FactoryBean */ Object postProcessAfterInitialization(Object bean, String beanName)throws BeansException; }
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { // 增强过的直接就返回null, // @return the bean instance to use, either the original or a wrapped one; // if {@code null}, no subsequent BeanPostProcessors will be invoked if (this.advisedBeans.containsKey(cacheKey)) { returnnull; } // Advice, Pointcut, Advisor, AopInfrastructureBean这些类直接跳过 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); returnnull; } }
// 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); } // Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; }
returnnull; }
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization /** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */ @Override public Object postProcessAfterInitialization(Object bean, String beanName)throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary /** * Wrap the given bean if necessary, i.e. if it is eligible for being proxied. * @param bean the raw bean instance * @param beanName the name of the bean * @param cacheKey the cache key for metadata access * @return a proxy wrapping the bean, or the raw bean instance as-is */ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey){ if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
/** * Find all eligible Advisors for auto-proxying this class. * @param beanClass the clazz to find advisors for * @param beanName the name of the currently proxied bean * @return the empty List, not {@code null}, * if there are no pointcuts or interceptors * @see #findCandidateAdvisors * @see #sortAdvisors * @see #extendAdvisors */ protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName){ // 找出当前beanFactory中的所有的Advisor List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 筛选出能用于当前beanClass的Advisor List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // 扩展点 extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { // 按照@Order定义的优先级排序 eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
/** * Find all candidate Advisors to use in auto-proxying. * @return the List of candidate Advisors */ protected List<Advisor> findCandidateAdvisors(){ returnthis.advisorRetrievalHelper.findAdvisorBeans(); }
// org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans /** * Find all eligible Advisor beans in the current bean factory, * ignoring FactoryBeans and excluding beans that are currently in creation. * @return the list of {@link org.springframework.aop.Advisor} beans * @see #isEligibleBean */ public List<Advisor> findAdvisorBeans(){ // Determine list of advisor bean names, if not cached already. String[] advisorNames = null; synchronized (this) { // 有缓存 advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the auto-proxy creator apply to them! advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } } if (advisorNames.length == 0) { returnnew LinkedList<Advisor>(); }
List<Advisor> advisors = new LinkedList<Advisor>(); // 遍历所有的advisor for (String name : advisorNames) { if (isEligibleBean(name)) { if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isDebugEnabled()) { logger.debug("Skipping currently created advisor '" + name + "'"); } } else { try { advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) { if (logger.isDebugEnabled()) { logger.debug("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage()); } // Ignore: indicates a reference back to the bean we're trying to advise. // We want to find advisors other than the currently created bean itself. continue; } } throw ex; } } } } return advisors; }
// org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors @Override protected List<Advisor> findCandidateAdvisors(){ // 上述的逻辑,从beanFactory中查找advisor // Add all the Spring advisors found according to superclass rules. List<Advisor> advisors = super.findCandidateAdvisors(); // AnnotationAwareAspectJAutoProxyCreator自己的逻辑 // Build Advisors for all AspectJ aspects in the bean factory. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; }
// org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors /** * Look for AspectJ-annotated aspect beans in the current bean factory, * and return to a list of Spring AOP Advisors representing them. * <p>Creates a Spring Advisor for each AspectJ advice method. * @return the list of {@link org.springframework.aop.Advisor} beans * @see #isEligibleBean */ public List<Advisor> buildAspectJAdvisors(){ List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new LinkedList<Advisor>(); aspectNames = new LinkedList<String>(); // 这里传入的是Object类,和上面传入的Advisor类不同 String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { if (!isEligibleBean(beanName)) { continue; } // We must be careful not to instantiate beans eagerly as in this case they // would be cached by the Spring container but would not have been weaved. Class<?> beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } // 是否是切面类,一般需要有@Aspect标记 if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { // 根据标记的类生成Advisor MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { // Per target or per this. if (this.beanFactory.isSingleton(beanName)) { thrownew IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton"); } MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName); this.aspectFactoryCache.put(beanName, factory); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } } // 初始化缓存的逻辑
/** * Create an {@link AopProxy} for the given AOP configuration. * @param config the AOP configuration in the form of an * AdvisedSupport object * @return the corresponding AOP proxy * @throws AopConfigException if the configuration is invalid */ AopProxy createAopProxy(AdvisedSupport config)throws AopConfigException;
}
//唯一的实现 org.springframework.aop.framework.DefaultAopProxyFactory @Override public AopProxy createAopProxy(AdvisedSupport config)throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { thrownew AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } // 实现了接口的,或者已经是JDK代理类 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { returnnew JdkDynamicAopProxy(config); } // CglibAopProxy 代理的子类 returnnew ObjenesisCglibAopProxy(config); } else { returnnew JdkDynamicAopProxy(config); } }
/** * Swap the target, returning the old target object. * @param newTarget the new target object * @return the old target object * @throws IllegalArgumentException if the new target is invalid */ publicsynchronized Object swap(Object newTarget)throws IllegalArgumentException { Assert.notNull(newTarget, "Target object must not be null"); Object old = this.target; this.target = newTarget; return old; }
有点类似jdk的AtomicReference,使用如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
@Bean public ProxyFactoryBean barFactory(HotSwappableTargetSource hotSwappableTargetSource){ ProxyFactoryBean pfb = new ProxyFactoryBean(); pfb.setTargetSource(hotSwappableTargetSource); pfb.setSingleton(false); return pfb; }
@Bean(name = "barTarget") @Scope(value = SCOPE_PROTOTYPE) public Bar barTarget(){ returnnew Bar(System.nanoTime()); }
@Bean public HotSwappableTargetSource hotSwappableTargetSource(Bar bar){ final HotSwappableTargetSource hotSwappableTargetSource = new HotSwappableTargetSource(bar); return hotSwappableTargetSource; }
// org.springframework.aop.target.CommonsPool2TargetSource#releaseTarget /** * Returns the specified object to the underlying {@code ObjectPool}. */ @Override publicvoidreleaseTarget(Object target)throws Exception { this.pool.returnObject(target); }
// org.springframework.aop.target.CommonsPool2TargetSource#getTarget /** * Borrows an object from the {@code ObjectPool}. */ @Override public Object getTarget()throws Exception { returnthis.pool.borrowObject(); }
/** * Return an IntroductionAdvisor that providing a mixin * exposing statistics about the pool maintained by this object. */ public DefaultIntroductionAdvisor getPoolingConfigMixin(){ DelegatingIntroductionInterceptor dii = new DelegatingIntroductionInterceptor(this); // 这个advisor的作用就是给生成的Target加了个接口PoolingConfig.class,这样后面拿到target之后就可以强转了 // 调用PoolingConfig接口中的方法就会给代理到当前的TargetSource returnnew DefaultIntroductionAdvisor(dii, PoolingConfig.class); }
try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } elseif (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } elseif (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } elseif (!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. // 从targetSource获取对应的信息 target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); }
// Get the interception chain for this method. // 获取针对targetClass的MethodInterceptor, @Aspect等声明的会在这个chain中 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()) { // 没有advised的,就直接用普通的jdk代理 // 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, // ReflectiveMethodInvocation类似filterChain,内部有状态记录处理到第几个,递归调用,使每个Interceptor都能执行 // 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; } elseif (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { thrownew 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可能是池化的,这里把对象归还给池子 targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
@Override public Object getProxy(ClassLoader classLoader){ if (logger.isDebugEnabled()) { logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource()); }
try { Class<?> rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
// 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数组,这个顺序要和CallBackFilter对应起来 Callback[] callbacks = getCallbacks(rootClass); // callback的类型 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 // callback对应的filter,filter的返回值决定了使用哪个下表的Callback enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); // callback的类型 enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance. // 生成代理类和实例 return createProxyClassAndInstance(enhancer, callbacks); } catch (CodeGenerationException ex) { thrownew AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class", ex); } catch (IllegalArgumentException ex) { thrownew AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class", ex); } catch (Exception ex) { // TargetSource.getTarget() failed thrownew AopConfigException("Unexpected AOP exception", ex); } }
// Choose an "aop" interceptor (used for AOP calls). // 1、最常用的Interceptor 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. // 2、这里区分动态的TargetSource和静态的,动态的比如底层是对象池,每次getTarget()都是不同的对象 // Dynamic的每次用完还需要releaseTarget 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). // 3. Callback targetDispatcher = isStatic ? new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
// 主要的几个callback Callback[] mainCallbacks = new 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, new EqualsInterceptor(this.advised), new HashCodeInterceptor(this.advised) };
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen, // then we can make some optimisations by sending the AOP calls // direct to the target using the fixed chain for that method. // 优化逻辑,tldr if (isStatic && isFrozen) { Method[] methods = rootClass.getMethods(); Callback[] fixedCallbacks = new Callback[methods.length]; this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);
// TODO: small memory optimisation here (can skip creation for methods with no advice) for (int x = 0; x < methods.length; x++) { List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass); fixedCallbacks[x] = new FixedChainStaticTargetInterceptor( chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass()); this.fixedInterceptorMap.put(methods[x].toString(), 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; }
CallbackFilter
再看CallbackFilter:
Implementation of CallbackFilter.accept() to return the index of the callback we need.
// org.springframework.aop.framework.CglibAopProxy.ProxyCallbackFilter#accept /** * Implementation of CallbackFilter.accept() to return the index of the * callback we need. * <p>The callbacks for each proxy are built up of a set of fixed callbacks * for general use and then a set of callbacks that are specific to a method * for use on static targets with a fixed advice chain. * <p>The callback used is determined thus: * <dl> * <dt>For exposed proxies</dt> * <dd>Exposing the proxy requires code to execute before and after the * method/chain invocation. This means we must use * DynamicAdvisedInterceptor, since all other interceptors can avoid the * need for a try/catch block</dd> * <dt>For Object.finalize():</dt> * <dd>No override for this method is used.</dd> * <dt>For equals():</dt> * <dd>The EqualsInterceptor is used to redirect equals() calls to a * special handler to this proxy.</dd> * <dt>For methods on the Advised class:</dt> * <dd>the AdvisedDispatcher is used to dispatch the call directly to * the target</dd> * <dt>For advised methods:</dt> * <dd>If the target is static and the advice chain is frozen then a * FixedChainStaticTargetInterceptor specific to the method is used to * invoke the advice chain. Otherwise a DynamicAdvisedInterceptor is * used.</dd> * <dt>For non-advised methods:</dt> * <dd>Where it can be determined that the method will not return {@code this} * or when {@code ProxyFactory.getExposeProxy()} returns {@code false}, * then a Dispatcher is used. For static targets, the StaticDispatcher is used; * and for dynamic targets, a DynamicUnadvisedInterceptor is used. * If it possible for the method to return {@code this} then a * StaticUnadvisedInterceptor is used for static targets - the * DynamicUnadvisedInterceptor already considers this.</dd> * </dl> */ @Override publicintaccept(Method method){ // final方法不代理 if (AopUtils.isFinalizeMethod(method)) { logger.trace("Found finalize() method - using NO_OVERRIDE"); return NO_OVERRIDE; } // 允许代理类被转为Advised, 且方法是Advised接口声明的 // 直接走dispatcher,返回对应的Advised 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; } // We must always proxy equals, to direct calls to this. // Equals方法的代理 if (AopUtils.isEqualsMethod(method)) { if (logger.isTraceEnabled()) { logger.trace("Found 'equals' method: " + method); } return INVOKE_EQUALS; } // We must always calculate hashCode based on the proxy. // HashCode方法的代理 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(); // 有advice,或者配置还能改 if (haveAdvice || !isFrozen) { // If exposing the proxy, then AOP_PROXY must be used. if (exposeProxy) { if (logger.isTraceEnabled()) { logger.trace("Must expose proxy on advised method: " + method); } return AOP_PROXY; } String key = method.toString(); // Check to see if we have fixed interceptor to serve this method. // Else use the AOP_PROXY. // 优化逻辑,暂时不看 if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) { 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(key); return (index + this.fixedInterceptorOffset); } else { if (logger.isTraceEnabled()) { logger.trace("Unable to apply any optimizations to advised method: " + method); } 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) { 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); } return INVOKE_TARGET; } else { if (logger.isTraceEnabled()) { logger.trace("Method return type ensures 'this' cannot be returned - " + "using DISPATCH_TARGET: " + method); } return DISPATCH_TARGET; } } }
// org.springframework.aop.framework.CglibAopProxy.AdvisedDispatcher /** * Dispatcher for any methods declared on the Advised class. */ privatestaticclassAdvisedDispatcherimplementsDispatcher, Serializable{
// org.springframework.aop.framework.CglibAopProxy.StaticDispatcher /** * Dispatcher for a static target. Dispatcher is much faster than * interceptor. This will be used whenever it can be determined that a * method definitely does not return "this" */ privatestaticclassStaticDispatcherimplementsDispatcher, Serializable{
// org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#buildLazyResourceProxy /** * Obtain a lazily resolving resource proxy for the given name and type, * delegating to {@link #getResource} on demand once a method call comes in. * @param element the descriptor for the annotated field/method * @param requestingBeanName the name of the requesting bean * @return the resource object (never {@code null}) * @since 4.2 * @see #getResource * @see Lazy */ protected Object buildLazyResourceProxy(final LookupElement element, final String requestingBeanName){ // 匿名的TargetSource TargetSource ts = new TargetSource() { @Override public Class<?> getTargetClass() { return element.lookupType; } @Override publicbooleanisStatic(){ returnfalse; } @Override public Object getTarget(){ // 这里实际去加载对应的类 return getResource(element, requestingBeanName); } @Override publicvoidreleaseTarget(Object target){ } }; // 生成代理类 ProxyFactory pf = new ProxyFactory(); pf.setTargetSource(ts); if (element.lookupType.isInterface()) { pf.addInterface(element.lookupType); } ClassLoader classLoader = (this.beanFactory instanceof ConfigurableBeanFactory ? ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() : null); return pf.getProxy(classLoader); }
Config配置类代理
有的系统有些祖传代码,写成这样:
1 2 3 4 5 6 7 8
@Configuration publicclassAppConfig{ @Bean public HuiPingDataSourceIdsBean getHuiPingDataSourceIdsBean(){ returnnew HuiPingDataSourceIdsBean(); } }
// org.springframework.context.annotation.ConfigurationClassPostProcessor#enhanceConfigurationClasses /** * Post-processes a BeanFactory in search of Configuration class BeanDefinitions; * any candidates are then enhanced by a {@link ConfigurationClassEnhancer}. * Candidate status is determined by BeanDefinition attribute metadata. * @see ConfigurationClassEnhancer */ publicvoidenhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory){ Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<String, AbstractBeanDefinition>(); // 遍历当前的bean for (String beanName : beanFactory.getBeanDefinitionNames()) { BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName); // 如果是full Configuration的标记了@Configuration if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) { if (!(beanDef instanceof AbstractBeanDefinition)) { thrownew BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" + beanName + "' since it is not stored in an AbstractBeanDefinition subclass"); } elseif (logger.isWarnEnabled() && beanFactory.containsSingleton(beanName)) { logger.warn("Cannot enhance @Configuration bean definition '" + beanName + "' since its singleton instance has been created too early. The typical cause " + "is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " + "return type: Consider declaring such methods as 'static'."); } // 加入到待处理集合 configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef); } } if (configBeanDefs.isEmpty()) { // nothing to enhance -> return immediately return; } // 这里出现了enhancer,内部是cglib的enhancer ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(); for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) { AbstractBeanDefinition beanDef = entry.getValue(); // If a @Configuration class gets proxied, always proxy the target class beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); try { // Set enhanced subclass of the user-specified bean class Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader); // 生成增强类 Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader); if (configClass != enhancedClass) { if (logger.isDebugEnabled()) { logger.debug(String.format("Replacing bean definition '%s' existing class '%s' with " + "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName())); } // 替换为增强类 beanDef.setBeanClass(enhancedClass); } } catch (Throwable ex) { thrownew IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex); } } }
测试代码:
1 2 3 4 5 6
@Test publicvoidtestConfigurationProxy(){ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class); final AopConfig aopConfig = context.getBean(AopConfig.class); log.info("aopConfig class = {}", aopConfig.getClass()); }
输出:
1
2021-03-09 16:04:16.978[main][INFO ]c.a.s.a.AopTest.testConfigurationProxy:132 aopConfig class = class com.air.spring.aop.AopConfig$$EnhancerBySpringCGLIB$$b88034a1