Spring源码解析(26)之AOP的核心对象创建过程

news2024/9/24 4:28:09

一、前言

        在上一节中我们介绍了在Spring 解析xml配置文件的时候,给我们往容器中生成了很多BeanDefinition,其中最重要的是advice对象,而advice对象最外层是用一个advisor对象包裹起来,而我们的advice对象的创建需要三个参数,第一个是MethodLocatingFactoryBean,第二个是AspectJExpressionPointcut对象,第三个是SimpleBeanFactoryAwareAspectInstanceFactory对象,如下图:

        具体的BeanDefinition如下图:

         Spring解析配置文件只是把这些advisor的BeanDefinition提前创建好了,但是这些对象创建放进去容器了吗?很明显是没有的,我们知道在refresh()方法中,finishBeanFactoryInitialization会提前创建非懒加载的bean,继续往下看。

	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		// 为上下文初始化类型转换器
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		// Register a default embedded value resolver if no bean post-processor
		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		// 如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器,主要用于注解属性值的解析
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		// 尽早初始化loadTimeWeaverAware bean,以便尽早注册它们的转换器
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		// 禁止使用临时类加载器进行类型匹配
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		// 冻结所有的bean定义,说明注册的bean定义将不被修改或任何进一步的处理
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		// 实例化剩下的单例对象
		beanFactory.preInstantiateSingletons();
	}

         在preInstantiateSingletons实例化剩下的Bean。

@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		// 将所有BeanDefinition的名字创建一个集合
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		// 触发所有非延迟加载单例bean的初始化,遍历集合的对象
		for (String beanName : beanNames) {
			// 合并父类BeanDefinition
 			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			// 条件判断,抽象,单例,非懒加载
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				// 判断是否实现了FactoryBean接口
				if (isFactoryBean(beanName)) {
					// 根据&+beanName来获取具体的对象
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					// 进行类型转换
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						// 判断这个FactoryBean是否希望立即初始化
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						//  如果希望急切的初始化,则通过beanName获取bean实例
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					// 如果beanName对应的bean不是FactoryBean,只是普通的bean,通过beanName获取bean实例
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		// 遍历beanNames,触发所有SmartInitializingSingleton的后初始化回调
		for (String beanName : beanNames) {
			// 获取beanName对应的bean实例
			Object singletonInstance = getSingleton(beanName);
			// 判断singletonInstance是否实现了SmartInitializingSingleton接口
			if (singletonInstance instanceof SmartInitializingSingleton) {
				// 类型转换
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				// 触发SmartInitializingSingleton实现类的afterSingletonsInstantiated方法
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

           

        我们接下来实例化的是logUtil这个类,以下就进入了熟悉的getBean方法,如果还不熟悉Spring生命周期的可以去看一下之前的博客,接下来我们继续放下跟。

	@Override
	public Object getBean(String name) throws BeansException {
		// 此方法是实际获取bean的方法,也是触发依赖注入的方法
		return doGetBean(name, null, null, false);
	}


	@Override
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

		/**
		 * 提取对应的beanName,很多同学可能会认为此处直接使用即可,为什么还要进行转换呢,原因在于当bean对象实现FactoryBean接口之后就会变成&beanName,同时如果存在别名,也需要把别名进行转换*/
		String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		/**提前检查单例缓存中是否有手动注册的单例对象,跟循环依赖有关联*/
		Object sharedInstance = getSingleton(beanName);
		// 如果bean的单例对象找到了,且没有创建bean实例时要使用的参数
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			// 返回对象的实例,很多同学会理解不了这句话存在的意义,当你实现了FactoryBean接口的对象,需要获取具体的对象的时候就需要此方法来进行获取了
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			// 当对象都是单例的时候会尝试解决循环依赖的问题,但是原型模式下如果存在循环依赖的情况,那么直接抛出异常
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			// 如果bean定义不存在,就检查父工厂是否有
			BeanFactory parentBeanFactory = getParentBeanFactory();
			// 如果beanDefinitionMap中也就是在所有已经加载的类中不包含beanName,那么就尝试从父容器中获取
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				// 获取name对应的规范名称【全类名】,如果name前面有'&',则会返回'&'+规范名称【全类名】
				String nameToLookup = originalBeanName(name);
				// 如果父工厂是AbstractBeanFactory的实例
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					// 调用父工厂的doGetBean方法,就是该方法。【递归】
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					// 如果有创建bean实例时要使用的参数
					// Delegation to parent with explicit args. 使用显示参数委派给父工厂
					// 使用父工厂获取该bean对象,通bean全类名和创建bean实例时要使用的参数
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					// 没有创建bean实例时要使用的参数 -> 委托给标准的getBean方法。
					// 使用父工厂获取该bean对象,通bean全类名和所需的bean类型
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					// 使用父工厂获取bean,通过bean全类名
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}
			// 如果不是做类型检查,那么表示要创建bean,此处在集合中做一个记录
			if (!typeCheckOnly) {
				// 为beanName标记为已经创建(或将要创建)
				markBeanAsCreated(beanName);
			}

			try {
				// 此处做了BeanDefinition对象的转换,当我们从xml文件中加载beandefinition对象的时候,封装的对象是GenericBeanDefinition,
				// 此处要做类型转换,如果是子类bean的话,会合并父类的相关属性
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				// 检查mbd的合法性,不合格会引发验证异常
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				// 如果存在依赖的bean的话,那么则优先实例化依赖的bean
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					// 如果存在依赖,则需要递归实例化依赖的bean
					for (String dep : dependsOn) {
						// 如果beanName已注册依赖于dependentBeanName的关系
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						// 注册各个bean的依赖关系,方便进行销毁
						registerDependentBean(dep, beanName);
						try {
							// 递归优先实例化被依赖的Bean
							getBean(dep);
						}
						// 捕捉为找到BeanDefinition异常:'beanName'依赖于缺少的bean'dep'
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// Create bean instance.
				// 创建bean的实例对象
				if (mbd.isSingleton()) {
					// 返回以beanName的(原始)单例对象,如果尚未注册,则使用singletonFactory创建并注册一个对象:
					sharedInstance = getSingleton(beanName, () -> {
						try {
							// 为给定的合并后BeanDefinition(和参数)创建一个bean实例
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							// 显示地从单例缓存中删除实例:它可能是由创建过程急切地放在那里,以允许循环引用解析。还要删除
							// 接收到该Bean临时引用的任何Bean
							// 销毁给定的bean。如果找到相应的一次性Bean实例,则委托给destoryBean
							destroySingleton(beanName);
							// 重新抛出ex
							throw ex;
						}
					});
					// 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
					// FactoryBean会直接返回beanInstance实例
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				// 原型模式的bean对象创建
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					// 它是一个原型 -> 创建一个新实例
					// 定义prototype实例
					Object prototypeInstance = null;
					try {
						// 创建Prototype对象前的准备工作,默认实现将beanName添加到prototypesCurrentlyInCreation中
						beforePrototypeCreation(beanName);
						// 为mbd(和参数)创建一个bean实例
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						// 创建完prototype实例后的回调,默认是将beanName从prototypesCurrentlyInCreation移除
						afterPrototypeCreation(beanName);
					}
					// 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
					// FactoryBean会直接返回beanInstance实例
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					// 指定的scope上实例化bean
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName)) {
						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
					}
					// 从scopes中获取scopeName对于的Scope对象
					Scope scope = this.scopes.get(scopeName);
					// 如果scope为null
					if (scope == null) {
						// 抛出非法状态异常:没有名为'scopeName'的scope注册
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						// 从scope中获取beanName对应的实例对象
						Object scopedInstance = scope.get(beanName, () -> {
							// 创建Prototype对象前的准备工作,默认实现 将beanName添加到prototypesCurrentlyInCreation中
							beforePrototypeCreation(beanName);
							try {
								// 为mbd(和参数)创建一个bean实例
								return createBean(beanName, mbd, args);
							}
							finally {
								// 创建完prototype实例后的回调,默认是将beanName从prototypesCurrentlyInCreation移除
								afterPrototypeCreation(beanName);
							}
						});
						// 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
						// FactoryBean会直接返回beanInstance实例
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						// 捕捉非法状态异常
						// 抛出Bean创建异常:作用域 'scopeName' 对于当前线程是不活动的;如果您打算从单个实例引用它,请考虑为此
						// beanDefinition一个作用域代理
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				// 捕捉获取Bean对象抛出的Bean异常
				// 在Bean创建失败后,对缓存的元数据执行适当的清理
				cleanupAfterBeanCreationFailure(beanName);
				// 重新抛出ex
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		// 检查requiredType是否与实际Bean实例的类型匹配
		// 如果requiredType不为null&&bean不是requiredType的实例
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				// 获取此BeanFactory使用的类型转换器,将bean转换为requiredType
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				// 如果convertedBean为null
				if (convertedBean == null) {
					// 抛出Bean不是必要类型的异常
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				// 返回convertedBean
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		// 将bean返回出去
		return (T) bean;
	}

        很明显这个Bean在缓存中是没有的,所以就会进入的createBean中去。

        这不知道大家是否记得,resolveBeforeInstantiation,这里是给一个机会BPP去创建对象。

	@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		// 如果beforeInstantiationResolved值为null或者true,那么表示尚未被处理,进行后续的处理
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			// 确认beanclass确实在此处进行处理
			// 判断当前mbd是否是合成的,只有在实现aop的时候synthetic的值才为true,并且是否实现了InstantiationAwareBeanPostProcessor接口
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				// 获取类型
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			// 是否解析了
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

         里面是两个关键条件,第一个条件mbd.isSynthetic(),是否是合成的,不知道在上一篇博客大家是否注意到了生成MethodLocadingBeanFactory中的属性设置,我们来看下。      

        这里就是标记是Spring合成的BeanDefinition,第二个条件是hasInstantiationAwareBeanPostProcessors(),这个条件就是在refresh方法中注册BPP的时候设置的属性值。继续往下跟。

	@Nullable
	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

        这里就是调用对应的BPP,这里我们直接看我们在解析配置文件的时候注入的AbstractAutoProxyCreator。

        我们看下isInfrastructureClass,判断是否是基础的bean。

	@Override
	protected boolean isInfrastructureClass(Class<?> beanClass) {
		// Previously we setProxyTargetClass(true) in the constructor, but that has too
		// broad an impact. Instead we now override isInfrastructureClass to avoid proxying
		// aspects. I'm not entirely happy with that as there is no good reason not
		// to advise aspects, except that it causes advice invocation to go through a
		// proxy, and if the aspect implements e.g the Ordered interface it will be
		// proxied by that interface and fail at runtime as the advice method is not
		// defined on the interface. We could potentially relax the restriction about
		// not advising aspects in the future.
		return (super.isInfrastructureClass(beanClass) ||
				(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
	}

	protected boolean isInfrastructureClass(Class<?> beanClass) {
		boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
				Pointcut.class.isAssignableFrom(beanClass) ||
				Advisor.class.isAssignableFrom(beanClass) ||
				AopInfrastructureBean.class.isAssignableFrom(beanClass);
		if (retVal && logger.isTraceEnabled()) {
			logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
		}
		return retVal;
	}

        我们这里创建的是logUtil很明显不是基础bean,接下来看shouldSkip的逻辑。

	@Override
	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		// TODO: Consider optimization by caching the list of the aspect names
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		for (Advisor advisor : candidateAdvisors) {
			// 判断这些创建的advisor的切面对象是否是当前bean,如果是则返回tre,表示不用创建代理对象
			if (advisor instanceof AspectJPointcutAdvisor &&
					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
				return true;
			}
		}
		return super.shouldSkip(beanClass, beanName);
	}

         findCandidateAdvisors这里是查找对应advisor对象,我们继续往下看这个方法。

	@Override
	protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		// 找到系统中实现了Advisor接口的bean
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		if (this.aspectJAdvisorsBuilder != null) {
			// 找到系统中使用@Aspect标注的bean,并且找到该bean中使用@Before,@After等标注的方法,
			// 将这些方法封装为一个个Advisor
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

	protected List<Advisor> findCandidateAdvisors() {
		Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
		// 获取所有的增强处理
		return this.advisorRetrievalHelper.findAdvisorBeans();
	}

public List<Advisor> findAdvisorBeans() {
		// Determine list of advisor bean names, if not cached already.
		String[] 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!
			// 获取当前BeanFactory中所有实现了Advisor接口的bean的名称
			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true, false);
			this.cachedAdvisorBeanNames = advisorNames;
		}
		if (advisorNames.length == 0) {
			return new ArrayList<>();
		}

		// 对获取到的实现Advisor接口的bean的名称进行遍历
		List<Advisor> advisors = new ArrayList<>();
		// 循环所有的beanName,找出对应的增强方法
		for (String name : advisorNames) {
			// isEligibleBean()是提供的一个hook方法,用于子类对Advisor进行过滤,这里默认返回值都是true
			if (isEligibleBean(name)) {
				// 如果当前bean还在创建过程中,则略过,其创建完成之后会为其判断是否需要织入切面逻辑
				if (this.beanFactory.isCurrentlyInCreation(name)) {
					if (logger.isTraceEnabled()) {
						logger.trace("Skipping currently created advisor '" + name + "'");
					}
				}
				else {
					try {
						// 将当前bean添加到结果中
						advisors.add(this.beanFactory.getBean(name, Advisor.class));
					}
					catch (BeanCreationException ex) {
						// 对获取过程中产生的异常进行封装
						Throwable rootCause = ex.getMostSpecificCause();
						if (rootCause instanceof BeanCurrentlyInCreationException) {
							BeanCreationException bce = (BeanCreationException) rootCause;
							String bceBeanName = bce.getBeanName();
							if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
								if (logger.isTraceEnabled()) {
									logger.trace("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;
	}

        这里就获取得到我们在之前配置文件中解析生成的所有advisor对象,获取得到这些对象之后,然后就会通过getBean来生成这些对象。 

         

        这里思考一个问题,我们创建一个advisor对象,我们来看下advisor对象的构造函数。

        很明显,我们创建advisor对象,那么就需要给他提前准备advice对象,我们接下继续看advice对象的构造函数。

        我们创建advice对象就需要提前创建好MethodLocadingBeanFactory对象,以及 AspectJExpressionPointcut和SimpleBeanFactoryAwareAspectInstanceFactory对象。

        所以总结一下,在AspectJAwareAdvisorAutoProxyCreator会找出所有的advisor对象,然后创建他们并且放入到缓存中,那么在创建advisor对象的时候也会提前创建advice对象,创建advice对象也会提前创建MethodLocadingBeanFactory对象,以及 AspectJExpressionPointcut和SimpleBeanFactoryAwareAspectInstanceFactory对象,这是一个递归调用getBean的过程。至于具体在哪调用,大家可以去看下我之前IOC生命周期的博客。

        这里就提前把Advisor对象给提前创建好了,然后就会判断当前类是否是切面对象,如果是切面对象,那就是应该跳过不创建代理对象。

 

        很明显logUtil就需要跳过并且返回null,所以在 resolveBeforeInstantiation方法中,如果是第一次调用那么他就会去寻找所有的Advisor对象,如果这些Advisor对象没有创建,那么就会创建他们,如果创建了那么就直接从容器中获取,如果获取得到了advisor对象,那么就会判断当前的对象是否是切面对象,如果是切面对象,那么就会跳过不创建代理对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1966443.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

|迁移学习| 迁移学习详解及基于pytorch的相关代码实现

&#x1f411; |迁移学习| 迁移学习详解及基于pytorch的相关代码实现 &#x1f411; 文章目录 &#x1f411; |迁移学习| 迁移学习详解及基于pytorch的相关代码实现 &#x1f411;&#x1f411; 前言&#x1f411;&#x1f411; 迁移学习详解&#x1f411;&#x1f411; 迁移学…

第34篇 子程序FINDSUM求和<一>

Q&#xff1a;如何设计汇编语言程序求数组[1:n]的和&#xff1f; A&#xff1a;基本原理&#xff1a;可编写一段实现子程序FINDSUM&#xff0c;子程序中使用一个loop来实现数组的求和运算。子程序FINDSUM的参数N存储在内存中&#xff0c;主程序从该内存中将其读取到一个寄存器…

MES系统如何实现生产任务的自动或辅助调度

MES系统&#xff08;Manufacturing Execution System&#xff0c;制造执行系统&#xff09;通过一系列集成化的功能模块和智能算法&#xff0c;实现生产任务的自动或辅助调度。以下是MES系统实现生产任务自动或辅助调度的具体方式&#xff1a; 1. 生产计划与排程 计划制定&am…

【C++从小白到大牛】类和对象

目录 一、面向过程和面向对象初步认识 二、类的引入 三、类的定义 类的成员函数两种定义方式&#xff1a; 1. 声明和定义全部放在类体中 2. 类声明放在.h文件中&#xff0c;成员函数定义放在.cpp文件中 成员变量命名规则的建议&#xff1a; 四、类的访问限定符 【访问限…

4.2.2、存储管理-段式存储和段页式存储

段式存储 段式存储是指将进程空间分为一个个段,每段也有段号和段内地址,与页式存储不同的是,每段物理大小不同,分段是根据逻辑整体分段的. 地址表示:(段号,段内偏移):其中段内偏移不能超过该段号对应的段长,否则越界错误,而此地址对应的真正内存地址应该是:段号对应的基地址段…

lambdafunctionbind

lambda匿名函数 定义&#xff1a; 捕捉&#xff1a;传值/传引用/mutable 混合捕捉&#xff0c;&#xff1d;表全普通捕捉 即使全部捕捉&#xff0c; 编译器实现时也不一定全部传入&#xff0c; 编译器只会传入要用到的变量 lambda内可使用的变量的范围 lambda内只能用捕捉对…

Linux gcc day 9

cpu是一个只可以执行指令&#xff0c;不是cpu要打印而是我们要打印&#xff0c;然后编译成指令再给cpu&#xff0c;再通过操作系统进行操手 进程状态&#xff1a; 为什么会有这些状态&#xff1f; 进程的多状态&#xff0c;本质都是为了满足未来不同的运行场景 有那些状态&am…

linux系统的检测脚本,用于检查linux的网络配置,包括网络接口状态、IP地址、子网掩码、默认网关、DNS服务器、连通性测试等等

目录 一、要求 二、脚本介绍 1、脚本内容 2、脚本解释 &#xff08;1&#xff09; 检查是否以 root 用户身份运行 &#xff08;2&#xff09;显示脚本标题 &#xff08;3&#xff09;打印主机名 &#xff08;4&#xff09;获取网络接口信息 &#xff08;5&#xff09…

React学习之props(父传子,子传父),Context组件之间的传参。

目录 前言 一、什么时候需要使用props&#xff1f; 二、使用 1.父传子 2.子传父 二、什么时候需要使用Context&#xff1f; 第一步: 第二步使用&#xff1a; 第一种&#xff1a; 第二种&#xff1a; 演示&#xff1a; 总结 前言 React学习笔记记录&#xff0c;pr…

python | TypeError: list indices must be integers or slices, not tuple

python | TypeError: list indices must be integers or slices, not tuple 在Python编程中&#xff0c;TypeError: list indices must be integers or slices, not tuple 是一个常见的错误。此错误通常发生在尝试使用非整数&#xff08;如元组&#xff09;作为列表索引时。本…

WSL和Windows建立TCP通信协议

1.windows配置 首先是windows端&#xff0c;启动TCP服务端&#xff0c;用来监听指定的端口号&#xff0c;其中IP地址可以设置为任意&#xff0c;否则服务器可能无法正常打开。 addrSer.sin_addr.S_un.S_addr INADDR_ANY; recv函数用来接收客户端传输的数据&#xff0c;其中…

游戏加速器哪个好用

对于游戏加速器&#xff0c;确实有很多不同的选择&#xff0c;每个加速器都有其独特的特点和优势。不过&#xff0c;我可以给你推荐一个最新上线的较受欢迎且评价较高的游戏加速器&#xff0c;供你参考&#xff1a; 深度加速器&#xff1a; 广泛支持&#xff1a;支持国内外众多…

RocketMQ批量消息

RocketMQ消息发送基本示例(推送消费者)-CSDN博客 RocketMQ消费者主动拉取消息示例-CSDN博客 RocketMQ顺序消息-CSDN博客 RocketMQ广播消息-CSDN博客 RocketMQ延时消息-CSDN博客 批量消息 批量消息是指将多条消息合并成一个批量消息,一次发送出去,原先的都是一次发一条.批量…

springboot四川旅游攻略分享互动平台-计算机毕业设计源码70222

摘 要 本研究基于Spring Boot框架开发了一款高效、可靠的四川旅游攻略分享互动平台。该系统主要面向管理员、普通用户和商家用户&#xff0c;涵盖了多个功能模块&#xff0c;包括旅游景点、旅游攻略、景点订单、酒店订单、酒店信息等。通过对系统需求的分析和设计&#xff0c;…

从数据规划到产品运营,拆解数据资产产品化的6大路径

数据资源入表对于企业数据资产的估值影响并不大&#xff0c;要想提升数据资产的整体价值&#xff0c;将数据资产进行产品化是更有效的途径之一。 那么&#xff0c;数据资产产品化的具体路径是怎样的&#xff1f; 在由WakeData惟客数据联合星光数智推出的直播栏目《星光对话》…

打破自闭症束缚:儿童康复案例揭秘

在自闭症的阴霾下&#xff0c;孩子们仿佛被困在一个无形的牢笼中&#xff0c;与外界的世界隔绝。然而&#xff0c;通过不懈的努力和科学的康复方法&#xff0c;许多孩子正在逐渐打破这一束缚&#xff0c;走向充满希望的未来。让我们一同走进几个令人鼓舞的儿童康复案例&#xf…

如何通过阿里云服务器部署hexo博客(超详细)

&#x1f44f;大家好&#xff01;我是和风coding&#xff0c;希望我的文章能给你带来帮助&#xff01; &#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&#x1f44d;一下博主哦 &#x1f4dd;点击 我的主页 还可以看到和风的其他内容噢&#x…

零基础入门转录组数据分析——机器学习算法之boruta(筛选特征基因)

零基础入门转录组数据分析——机器学习算法之boruta&#xff08;筛选特征基因&#xff09; 目录 零基础入门转录组数据分析——机器学习算法之boruta&#xff08;筛选特征基因&#xff09;1. boruta基础知识2. boruta&#xff08;Rstudio&#xff09;——代码实操2. 1 数据处理…

[Docker][Docker Volume]详细讲解

目录 1.什么是存储卷&#xff1f;2.为什么需要存储卷&#xff1f;1.数据丢失问题2.性能问题3.宿主机和容器互访不方便4.容器和容器共享不方便 3.存储卷分类1.volume docker 管理卷2.bind mount 绑定数据卷3.tmpfs mount 临时数据卷 5.管理卷 Volume1.创建卷1.-v 参数2.--mount …

《Milvus Cloud向量数据库指南》——向量数据库性价比大比拼:谁才是性能之王?

在分析这份向量数据库(Vector Databases)的性价比排名表格时,我们需要从多个维度深入探讨,包括但不限于硬件配置、价格/性能比(QP$,即每百万次查询所花费的价格)、数据集大小、查询类型(无标量过滤、低标量过滤、高标量过滤)以及不同服务提供商之间的比较。以下是一个…