Spring源码分析(三) bean的生命周期 createBean()和doCreateBean()

1、createBean()

resolveBeforeInstantiation 也要详细介绍 打标机

java 复制代码
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		if (logger.isTraceEnabled()) {
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		// 锁定class,根据设置的class属性或者根据className来解析class
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		// 进行条件筛选,重新赋值RootBeanDefinition,并设置BeanClass属性
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			// 重新创建一个RootBeanDefinition对象
			mbdToUse = new RootBeanDefinition(mbd);
			// 设置BeanClass属性值
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		// 验证及准备覆盖的方法,lookup-method  replace-method,当需要创建的bean对象中包含了lookup-method和replace-method标签的时候,会产生覆盖操作
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			// 给BeanPostProcessors一个机会来返回代理来替代真正的实例,应用实例化前的前置处理器,用户自定义动态代理的方式,针对于当前的被代理类需要经过标准的代理流程来创建对象
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			// 实际创建bean的调用
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

1.1 resolveBeanClass()

锁定class,根据设置的class属性或者根据className 来解析 Class

java 复制代码
@Nullable
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch) {
	if (mbd.hasBeanClass()) {
		return mbd.getBeanClass();
	}
	if (System.getSecurityManager() != null) {
		return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
				() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
	} else {
		return doResolveBeanClass(mbd, typesToMatch);
	}
}

@Nullable
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch) {
	ClassLoader beanClassLoader = getBeanClassLoader();
	ClassLoader classLoaderToUse = beanClassLoader;
	if (!ObjectUtils.isEmpty(typesToMatch)) {
		// When just doing type checks (i.e. not creating an actual instance yet),
		// use the specified temporary class loader (e.g. in a weaving scenario).
		ClassLoader tempClassLoader = getTempClassLoader();
		if (tempClassLoader != null) {
			classLoaderToUse = tempClassLoader;
			if (tempClassLoader instanceof DecoratingClassLoader) {
				DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
				for (Class<?> typeToMatch : typesToMatch) {
					dcl.excludeClass(typeToMatch.getName());
				}
			}
		}
	}
	String className = mbd.getBeanClassName();
	if (className != null) {
		Object evaluated = evaluateBeanDefinitionString(className, mbd);
		if (!className.equals(evaluated)) {
			// A dynamically resolved expression, supported as of 4.2...
			if (evaluated instanceof Class) {
				return (Class<?>) evaluated;
			} else if (evaluated instanceof String) {
				return ClassUtils.forName((String) evaluated, classLoaderToUse);
			}
		}
		// When resolving against a temporary class loader, exit early in order
		// to avoid storing the resolved Class in the bean definition.
		if (classLoaderToUse != beanClassLoader) {
			return ClassUtils.forName(className, classLoaderToUse);
		}
	}
	return mbd.resolveBeanClass(beanClassLoader);
}

1.2 prepareMethodOverrides()

对Override属性标记及验证,在 Spring 配置中存在 lookup - method 和 replace - method 两个配置功能,而这两个配置的加载其实就是将配置统一存放在 BeanDefinition 中的 methodOverrides 属性里,这两个功能实现原理其实是在 bean 实例化的时候如果检测到存在 methodOverrides 属性,会动态地为当前 bean 生成代理并使用对应的拦截器为 bean 做增强处理。

对于方法的匹配来讲,如果一个类中存在若干个重载方法,那么,在函数调用及增强的时候还需要根据参数类型进行匹配,来最终确认当前调用的到底是哪个函数。如果当前类中的方法只有一个,那么就设置重载该方法没有被重载,这样在后续调用的时候便可以直接使用找到的方法,而不需要进行方法的参数匹配验证了,而且还可以提前对方法存在性进行验证。

java 复制代码
	/**
	 * Validate and prepare the method overrides defined for this bean. 验证并准备为此 bean 定义的方法覆盖。
	 * Checks for existence of a method with the specified name. 检查具有指定名称的方法是否存在。
	 * @throws BeanDefinitionValidationException in case of validation failure
	 */
	public void prepareMethodOverrides(){
		// Check that lookup methods exist and determine their overloaded status.
		if (hasMethodOverrides()) {
			// MethodOverrides methodOverrides = new MethodOverrides();
			// final Set<MethodOverride> overrides = new CopyOnWriteArraySet<>();
			getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
		}
	}

	/**
	 * Validate and prepare the given method override.
	 * Checks for existence of a method with the specified name,
	 * marking it as not overloaded if none found.
	 * @param mo the MethodOverride object to validate
	 * @throws BeanDefinitionValidationException in case of validation failure
	 */
	protected void prepareMethodOverride(MethodOverride mo) {
		// 获取对应方法名的个数
		int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
		if (count == 1) {
			// 标记 MethodOverrides 为未覆盖,避免参数类型检查的开销
			// Mark override as not overloaded, to avoid the overhead of arg type checking.
			mo.setOverloaded(false);
		}
	}	

1.3 resolveBeforeInstantiation()

实例化的前置处理,对后处理器中的所有 InstantiationAwareBeanPostProcessor 类型的后处理器 调用 postProcessBeforelnstantiation() 和 BeanPostProcessor 的 postProcessAfterInitialization()。

java 复制代码
	/**
	 * 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) {
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}	

1.3.1 applyBeanPostProcessorsBeforeInstantiation()

在 bean 的实例化前会调用后处理器的方法进行处理

bean 的实例化前调用,给子类一个修改 BeanDefinition 的机会,也就是说当程序经过这个方法后, bean 可能已经不是我们认为的 bean 了,而是或许成为了一个经过处理的代理 bean ,可能是通过 cglib 生成的,也可能是通过其他技术生成的。aop的相关有些类就是在这边提前处理了。
这里也可以自己扩展不过一般用不到

扩展点1:实现InstantiationAwareBeanPostProcessor 接口

java 复制代码
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    /**
     * 实例化之前的操作
     */
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    		// 这里也可以返回普通对象
            System.out.println("当前beanName:" + beanName + "--> 执行:postProcessBeforeInstantiation 实例化之前");
            if (beanClass == MyConfig.class) {
                // 创建动态代理类的增强类
                Enhancer enhancer = new Enhancer();
                //  设置类加载器
                enhancer.setClassLoader(beanClass.getClassLoader());
                //  设置被动态代理类所代理的 被代理类
                enhancer.setSuperclass(beanClass);
                // 设置方法拦截器
                enhancer.setCallback(new QzkMethodInterceptor());
                //  创建代理类
                BeforeInstantiation beforeInstantiation = (BeforeInstantiation) enhancer.create();
                System.out.println("创建代理对象:" + beforeInstantiation);
                return beforeInstantiation;
            }
            return nulll;
    }

    /**
     * 实例化之后的操作
     */
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    	// MyConfig config = (MyConfig)bean; 这里也可以调整 属性的值或者其他操作
    	//其实就是 相当于 经历spring的完整的对象创建过程然后调整属性的值的一个操作
        config.age=10;
        System.out.println("当前beanName:" + beanName + "--> 执行:postProcessAfterInstantiation 实例化之后");
        return false;
    }

    /**
     * 对当前属性值的一个相关处理工作
     */
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        System.out.println("当前beanName:" + beanName + "--> 执行:postProcessProperties 属性值的处理");
        return pvs;
    }

    /**
     * 初始化之前的做哪些操作
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("当前beanName:" + beanName + "--> 执行:postProcessBeforeInitialization 初始化之前");

        return bean;
    }

    /**
     * 初始化之后做哪些操作
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("当前beanName:" + beanName + "--> 执行:postProcessAfterInitialization 初始化之后");
        return bean;
    }
}

1.3.2 applyBeanPostProcessorsAfterInitialization()

实例化后的后处理器应用,Spring 中的规则是在 bean 的初始化后尽可能保证将注册的后处理器的 postProcessAfterlnitialization() 应用到该 bean 中,因为如果返回的 bean 不为空,那么便不会再次经历普通 bean 的创建过程,所以只能在这里应用后处理器的 postProcessAfterInitialization()。

2、doCreateBean()

整体的流程如下,每个细节过程还有具体的图,整体的可能看不清

java 复制代码
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		// 这个beanWrapper是用来持有创建出来的bean对象的
		BeanWrapper instanceWrapper = null;
		// 获取factoryBean实例缓存
		if (mbd.isSingleton()) {
			// 如果是单例对象,从factorybean实例缓存中移除当前bean定义信息
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		// 没有就创建实例
		if (instanceWrapper == null) {
			// 根据执行bean使用对应的策略创建新的实例,如,工厂方法,构造函数主动注入、简单初始化
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		// 从包装类中获取原始bean
		Object bean = instanceWrapper.getWrappedInstance();
		// 获取具体的bean对象的Class属性
		Class<?> beanType = instanceWrapper.getWrappedClass();
		// 如果不等于NullBean类型,那么修改目标类型
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		// 允许beanPostProcessor去修改合并的beanDefinition
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					// MergedBeanDefinitionPostProcessor后置处理器修改合并bean的定义
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		// 判断当前bean是否需要提前曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			// 为避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		// 初始化bean实例
		Object exposedObject = bean;
		try {
			// 对bean的属性进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的bean
			populateBean(beanName, mbd, instanceWrapper);
			// 执行初始化逻辑
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
			// 从缓存中获取具体的对象
			Object earlySingletonReference = getSingleton(beanName, false);
			// earlySingletonReference只有在检测到有循环依赖的情况下才会不为空
			if (earlySingletonReference != null) {
				// 如果exposedObject没有在初始化方法中被改变,也就是没有被增强
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						// 返回false说明依赖还没实例化好
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					// 因为bean创建后所依赖的bean一定是已经创建的
					// actualDependentBeans不为空则表示当前bean创建后其依赖的bean却没有全部创建完,也就是说存在循环依赖
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			// 注册bean对象,方便后续在容器销毁的时候销毁对象
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

2.1 createBeanInstance()

java 复制代码
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		// 确认需要创建的bean实例的类可以实例化
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		// 确保class不为空,并且访问权限是public
		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		// 判断当前beanDefinition中是否包含实例供应器,此处相当于一个回调方法,利用回调方法来创建bean
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		// 如果工厂方法不为空则使用工厂方法初始化策略
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器
		// 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析

		// Shortcut when re-creating the same bean...
		// 标记下,防止重复创建同一个bean
		boolean resolved = false;
		// 是否需要自动装配
		boolean autowireNecessary = false;
		// 如果没有参数
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				// 因为一个类可能由多个构造函数,所以需要根据配置文件中配置的参数或传入的参数来确定最终调用的构造函数。
				// 因为判断过程会比较,所以spring会将解析、确定好的构造函数缓存到BeanDefinition中的resolvedConstructorOrFactoryMethod字段中。
				// 在下次创建相同时直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值获取,避免再次解析
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		// 有构造参数的或者工厂方法
		if (resolved) {
			// 构造器有参数
			if (autowireNecessary) {
				// 构造函数自动注入
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				// 使用默认构造函数构造
				return instantiateBean(beanName, mbd);
			}
		}

		// Candidate constructors for autowiring?
		// 从bean后置处理器中为自动装配寻找构造方法, 有且仅有一个有参构造或者有且仅有@Autowired注解构造
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		// 以下情况符合其一即可进入
		// 1、存在可选构造方法
		// 2、自动装配模型为构造函数自动装配
		// 3、给BeanDefinition中设置了构造参数值
		// 4、有参与构造函数参数列表的参数
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// Preferred constructors for default construction?
		// 找出最合适的默认构造方法
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			// 构造函数自动注入
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// No special handling: simply use no-arg constructor.
		// 使用默认无参构造函数创建对象,如果没有无参构造且存在多个有参构造且没有@AutoWired注解构造,会报错
		return instantiateBean(beanName, mbd);
	}

总结: bean对象的创建方式

2.2 applyMergedBeanDefinitionPostProcessors()

应用MergedBeanDefinitionPostProcessors类型的beanPostProcessor到指定的beanDefinition中

执行postProcessMergedBeanDefinition方法,这里主要是为了合并bean的定义的。

其中 执行的类有主要以下3个

AutowiredAnnotataionBeanPostProcessor处理@Autowired,@Value注解

CommonAnnotationBeanPostProcessor处理@Resource

InitDestroyAnnotationBeanPostProcessor处理@PostConstruct,@PreDestroy

java 复制代码
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof MergedBeanDefinitionPostProcessor) {
				MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
				bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
			}
		}
	}

	/**
	 *spring通过此方法找出所有需要注入的字段,同时做缓存
	 * 这个接口下有很多的实现类,最常见的就是
	 * AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor
	 * Post-process the given merged bean definition for the specified bean.
	 * @param beanDefinition the merged bean definition for the bean
	 * @param beanType the actual type of the managed bean instance
	 * @param beanName the name of the bean
	 * @see AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
	 */
	void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

	

2.2.1 CommonAnnotationBeanPostProcessor

java 复制代码
@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		// 处理@PostConstruct和@PreDestroy注解
		super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
		//找出beanType所有被@Resource标记的字段和方法封装到InjectionMetadata中
		InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}

/**
	 * 解析@Resource注解
	 * @param beanName
	 * @param clazz
	 * @param pvs
	 * @return
	 */
	private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
		// Fall back to class name as cache key, for backwards compatibility with custom callers.
		// 获取对应的bean名称作为缓存key
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// Quick check on the concurrent map first, with minimal locking.
		// 从缓存中获取注入元数据对象
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if (metadata != null) {
						metadata.clear(pvs);
					}
					// 将返回的metadata对象放入injectionMetadataCache缓存中,缓存key为beanName,供后续方法从缓存中取出
					metadata = buildResourceMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

	private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
		// 判断当前clazz是否是候选class
		if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}

		// 创建InjectedElement集合对象
		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;

		do {
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

			// 查询是否有webService,ejb,Resource的属性注解,但是不支持静态属性
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
					if (Modifier.isStatic(field.getModifiers())) {
						throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
					}
					currElements.add(new WebServiceRefElement(field, field, null));
				}
				else if (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
					if (Modifier.isStatic(field.getModifiers())) {
						throw new IllegalStateException("@EJB annotation is not supported on static fields");
					}
					currElements.add(new EjbRefElement(field, field, null));
				}
				else if (field.isAnnotationPresent(Resource.class)) {
					//注意静态字段不支持
					if (Modifier.isStatic(field.getModifiers())) {
						throw new IllegalStateException("@Resource annotation is not supported on static fields");
					}
					//如果不想注入某一类型对象 可以将其加入ignoredResourceTypes中
					if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
						//字段会封装到ResourceElement
						currElements.add(new ResourceElement(field, field, null));
					}
				}
			});

			// 处理方法
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				//找出我们在代码中定义的方法而非编译器为我们生成的方法
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
				//如果重写了父类的方法,则使用子类的
				if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
						// 静态字段不支持
						if (Modifier.isStatic(method.getModifiers())) {
							throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
						}
						if (method.getParameterCount() != 1) {
							throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
						}
						PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
						currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
					}
					else if (ejbClass != null && bridgedMethod.isAnnotationPresent(ejbClass)) {
						if (Modifier.isStatic(method.getModifiers())) {
							throw new IllegalStateException("@EJB annotation is not supported on static methods");
						}
						if (method.getParameterCount() != 1) {
							throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
						}
						PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
						currElements.add(new EjbRefElement(method, bridgedMethod, pd));
					}
					else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
						// 不支持静态方法
						if (Modifier.isStatic(method.getModifiers())) {
							throw new IllegalStateException("@Resource annotation is not supported on static methods");
						}
						Class<?>[] paramTypes = method.getParameterTypes();
						if (paramTypes.length != 1) {
							throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
						}
						if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
							PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
							currElements.add(new ResourceElement(method, bridgedMethod, pd));
						}
					}
				}
			});

			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

		return InjectionMetadata.forElements(elements, clazz);
	}

2.2.2 InitDestroyAnnotationBeanPostProcessor

java 复制代码
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		// 调用方法获取生命周期元数据并保存
		LifecycleMetadata metadata = findLifecycleMetadata(beanType);
		// 验证相关方法
		metadata.checkConfigMembers(beanDefinition);
	}

private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
		if (this.lifecycleMetadataCache == null) {
			// Happens after deserialization, during destruction...
			// 在bean销毁过程中,反序列化后调用
			return buildLifecycleMetadata(clazz);
		}
		// Quick check on the concurrent map first, with minimal locking.
		// 首先尝试从缓存中获取元数据
		LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
		// 如果从缓存中获取失败则尝试加锁创建元数据
		if (metadata == null) {
			synchronized (this.lifecycleMetadataCache) {
				// 加锁后再次尝试获取元数据,防止多线程重复执行
				metadata = this.lifecycleMetadataCache.get(clazz);
				if (metadata == null) {
					// 构建生命周期元数据
					metadata = buildLifecycleMetadata(clazz);
					// 将构建好的元数据放入缓存中
					this.lifecycleMetadataCache.put(clazz, metadata);
				}
				return metadata;
			}
		}
		return metadata;
	}

	/**
	 * 构造生命周期元数据(解析带@PostConstruct和@PreDestroy注解的方法),当其构造完成后会将元数据缓存到lifecycleMetadataCache集合中并返回
	 * 此时就完成了相关方法(初始化方法和销毁方法)的扫描解析和缓存工作
	 *
	 * @param clazz
	 * @return
	 */
	private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
		if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
			return this.emptyLifecycleMetadata;
		}

		// 实例化后的回调方法(@PostConstruct)
		List<LifecycleElement> initMethods = new ArrayList<>();
		// 销毁前的回调方法(@PreDestroy)
		List<LifecycleElement> destroyMethods = new ArrayList<>();
		// 获取正在处理的目标类
		Class<?> targetClass = clazz;

		do {
			// 保存每一轮循环搜索到的相关方法
			final List<LifecycleElement> currInitMethods = new ArrayList<>();
			final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
			// 反射获取当前类中的所有方法并依次对其调用第二个参数的lambda表达式
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				// 当前方法的注解中包含initAnnotationType注解时(@PostConstruct)
				if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
					// 如果有,把它封装成LifecycleElement对象,存储起来
					LifecycleElement element = new LifecycleElement(method);
					// 将创建好的元素添加到集合中
					currInitMethods.add(element);
					if (logger.isTraceEnabled()) {
						logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
					}
				}
				// 当前方法的注解中包含destroyAnnotationType注解(PreDestroy)
				if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
					// 如果有,把它封装成LifecycleElement对象,存储起来
					currDestroyMethods.add(new LifecycleElement(method));
					if (logger.isTraceEnabled()) {
						logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
					}
				}
			});

			// 将本次循环中获取到的对应方法集合保存到总集合中
			initMethods.addAll(0, currInitMethods);
			// 销毁方法父类晚于子类
			destroyMethods.addAll(currDestroyMethods);
			// 获取当前类的父类
			targetClass = targetClass.getSuperclass();
		}
		// 如果当前类存在父类且父类不为object基类则循环对父类进行处理
		while (targetClass != null && targetClass != Object.class);

		// 有一个不为空就封装一个LifecycleMetadata对象,否则就返回空的emptyLifecycleMetadata
		return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
				new LifecycleMetadata(clazz, initMethods, destroyMethods));
	}

2.2.3 AutowiredAnnotationBeanPostProcessor

java 复制代码
/**
	 * 处理合并的bean定义信息
	 * 1、解析@Autowired等注解然后转换
	 * 2、把注解信息转换为InjectionMetadata然后缓存到上面的injectionMetadataCache里面
	 * @param beanDefinition the merged bean definition for the bean
	 * @param beanType the actual type of the managed bean instance
	 * @param beanName the name of the bean
	 */
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		// 解析注解并缓存
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}
java 复制代码
/**
	 *  方法名为查找到该bean的依赖注入元信息,内部只要查找到了就会加入到缓存内,下次没必要再重复查找了~
	 * 	它是一个模版方法,真正做事的方法是:buildAutowiringMetadata,它复杂把标注有@Autowired注解的属性转换为Metadata元数据信息,从而消除注解的定义
	 * 	此处查找包括了字段依赖注入和方法依赖注入~~~
	 * @param beanName
	 * @param clazz
	 * @param pvs
	 * @return
	 */
	private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
		// Fall back to class name as cache key, for backwards compatibility with custom callers.
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// Quick check on the concurrent map first, with minimal locking.
		// 从缓存中获取该类的信息
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		// 判断是否需要刷新缓存
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if (metadata != null) {
						metadata.clear(pvs);
					}
					// 构建自动装配的属性和方法元数据
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

	/**
	 * 去寻找有Autowired和Value注解的属性和方法,也包括自定义的父类的,封装成AutowiredMethodElement放入集合中
	 * @param clazz
	 * @return
	 */
	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		// 如果clazz是JDK中的类,直接忽略,因为不可能标注有这些标注
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}

		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;

		do {
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

			// 遍历类中的每个属性,判断属性是否包含指定的属性(通过 findAutowiredAnnotation 方法)
			// 如果存在则保存,这里注意,属性保存的类型是 AutowiredFieldElement
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
					//Autowired注解不支持静态方法
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					//查看是否是required的
					boolean required = determineRequiredStatus(ann);
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});


			// 遍历类中的每个方法,判断属性是否包含指定的属性(通过 findAutowiredAnnotation 方法)
			// 如果存在则保存,这里注意,方法保存的类型是 AutowiredMethodElement
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					// 如果方法没有入参,输出日志,不做任何处理
					if (method.getParameterCount() == 0) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					boolean required = determineRequiredStatus(ann);
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					// AutowiredMethodElement里封装了一个PropertyDescriptor(比字段多了一个参数)
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});

			// 父类的都放在第一位,所以父类是最先完成依赖注入的
			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

		// InjectionMetadata就是对clazz和elements的一个包装而已
		return InjectionMetadata.forElements(elements, clazz);
	}

2.3 populateBean()

该方法的核心流程主要就是填充属性,

一部分代码是支持老的xml的注入的方式

一部分是支持新式的注解的方式例如像@Resource,@Autowired注解,这一部分的关键代码就在于postProcessProperties()中

java 复制代码
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		// 如果beanWrapper为空
		if (bw == null) {
			// 如果mbd有需要设置的属性
			if (mbd.hasPropertyValues()) {
				// 抛出bean创建异常
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
				// Skip property population phase for null instance.
				// 没有可填充的属性,直接跳过
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		// 给任何实现了InstantiationAwareBeanPostProcessors的子类机会去修改bean的状态再设置属性之前,可以被用来支持类型的字段注入

		// 否是"synthetic"。一般是指只有AOP相关的pointCut配置或者Advice配置才会将 synthetic设置为true
		// 如果mdb是不是'syntheic'且工厂拥有InstantiationAwareBeanPostProcessor
		// 这里可以写接口可以让所有类都不能依赖注入
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			//遍历工厂中的BeanPostProcessor对象
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				//如果 bp 是 InstantiationAwareBeanPostProcessor 实例
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					// //postProcessAfterInstantiation:一般用于设置属性
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						return;
					}
				}
			}
		}
		//PropertyValues:包含以一个或多个PropertyValue对象的容器,通常包括针对特定目标Bean的一次更新
		//如果mdb有PropertyValues就获取其PropertyValues
		//这个是程序员在 bd中 写入的属性rootBeanDefinition.getPropertyValues().add("type","男的");或者是XML中定义Bean的时候 加的PropertyValue标签
 		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		// 获取 mbd 的 自动装配模式
		// 这里正常时用来依赖注入 以前xml方式配置的那种
		// <bean id="person" class="com.Person" autowire="byName"></bean>
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		// 如果 自动装配模式 为 按名称自动装配bean属性 或者 按类型自动装配bean属性
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			//MutablePropertyValues:PropertyValues接口的默认实现。允许对属性进行简单操作,并提供构造函数来支持从映射 进行深度复制和构造
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			// 根据autotowire的名称(如适用)添加属性值
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				//通过bw的PropertyDescriptor属性名,查找出对应的Bean对象,将其添加到newPvs中
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			// 根据自动装配的类型(如果适用)添加属性值
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				//通过bw的PropertyDescriptor属性类型,查找出对应的Bean对象,将其添加到newPvs中
				autowireByType(beanName, mbd, bw, newPvs);
			}
			//让pvs重新引用newPvs,newPvs此时已经包含了pvs的属性值以及通过AUTOWIRE_BY_NAME,AUTOWIRE_BY_TYPE自动装配所得到的属性值
			pvs = newPvs;
		}

		//这里是对非autowiring的属性进行依赖注入处理
		//工厂是否拥有InstiationAwareBeanPostProcessor
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		//mbd.getDependencyCheck(),默认返回 DEPENDENCY_CHECK_NONE,表示 不检查
		//是否需要依赖检查
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		//经过筛选的PropertyDesciptor数组,存放着排除忽略的依赖项或忽略项上的定义的属性
		PropertyDescriptor[] filteredPds = null;
		//如果工厂拥有InstiationAwareBeanPostProcessor,那么处理对应的流程,主要是对几个注解的赋值工作包含的两个关键子类是CommonAnnoationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor
		if (hasInstAwareBpps) {
			//如果pvs为null
			if (pvs == null) {
				//尝试获取mbd的PropertyValues
				pvs = mbd.getPropertyValues();
			}
			//遍历工厂内的所有后置处理器
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				//如果 bp 是 InstantiationAwareBeanPostProcessor 的实例
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					//将bp 强转成 InstantiationAwareBeanPostProcessor 对象
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					//postProcessProperties:在工厂将给定的属性值应用到给定Bean之前,对它们进行后处理,不需要任何属性扫描符。
					// 让ibp对pvs增加对bw的Bean对象的propertyValue,或编辑pvs的proertyValue
					//依赖注入过程,@Autowired、@Resource、@Value等注解的注入
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					//如果pvs为null
					if (pvsToUse == null) {
						//如果filteredPds为null
						if (filteredPds == null) {
							//mbd.allowCaching:是否允许缓存,默认时允许的。缓存除了可以提高效率以外,还可以保证在并发的情况下,返回的PropertyDesciptor[]永远都是同一份
							//从bw提取一组经过筛选的PropertyDesciptor,排除忽略的依赖项或忽略项上的定义的属性
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						// 老版本用这个完成依赖注入过程,@Autowired的支持
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						//如果pvsToUse为null,将终止该方法精致,以跳过属性填充
						if (pvsToUse == null) {
							return;
						}
					}
					//让pvs引用pvsToUse
					pvs = pvsToUse;
				}
			}
		}
		//如果需要依赖检查
		if (needsDepCheck) {
			//如果filteredPds为null
			if (filteredPds == null) {
				//从bw提取一组经过筛选的PropertyDesciptor,排除忽略的依赖项或忽略项上的定义的属性
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			//检查依赖项:主要检查pd的setter方法需要赋值时,pvs中有没有满足其pd的需求的属性值可供其赋值
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

	
		//这个方法建议不看,是老版本用<property name="xxx" value="xxx"/>这种标签才会进来的。
		//标签做依赖注入的代码实现,里面超鸡儿复杂。现在都用注解了可以不看
		if (pvs != null) {
			//应用给定的属性值,解决任何在这个bean工厂运行时其他bean的引用。必须使用深拷贝,所以我们 不会永久地修改这个属性
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

2.3.1 postProcessProperties()

这个其实再上面的applyMergedBeanDefinitionPostProcessors()方法中已经讲过了 ,上面那个是会先提前读取 然后放入对应的缓存中 ,再这边是直接 读取缓存的。然后进行注入,采用反射的方式进行。这里只讲注入的代码段

AutowiredAnnotationBeanPostProcessor

java 复制代码
@AutoWired
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			metadata.inject(bean, beanName, pvs);
		}
		catch (BeanCreationException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}


private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
		// Fall back to class name as cache key, for backwards compatibility with custom callers.
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// Quick check on the concurrent map first, with minimal locking.
        //此处缓存中有数据,直接就返回了
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if (metadata != null) {
						metadata.clear(pvs);
					}
					//这个重要方法上篇分享过了,这里就不说了
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
		Collection<InjectedElement> checkedElements = this.checkedElements;
		Collection<InjectedElement> elementsToIterate =
				(checkedElements != null ? checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
            //循环每个带有@Atowared注解的参数或者方法,依次通过反射赋值
			for (InjectedElement element : elementsToIterate) {
				if (logger.isTraceEnabled()) {
					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
				}//反射核心方法,处理参数或者方法,点击
				element.inject(target, beanName, pvs);
			}
		}
	}

element.inject(target, beanName, pvs);方法:参数赋值
	@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				desc.setContainingClass(bean.getClass());
				Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try {
					//这里会触发依赖注入属性的getBean操作,前几篇分析过,此处省略
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
				synchronized (this) {
					if (!this.cached) {
						if (value != null || this.required) {
							this.cachedFieldValue = desc;
							registerDependentBeans(beanName, autowiredBeanNames);
							if (autowiredBeanNames.size() == 1) {
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								if (beanFactory.containsBean(autowiredBeanName) &&
										beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
									this.cachedFieldValue = new ShortcutDependencyDescriptor(
											desc, autowiredBeanName, field.getType());
								}
							}
						}
						else {
							this.cachedFieldValue = null;
						}
						this.cached = true;
					}
				}
			}
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
                //最终通过反射赋值,参数如下。
				field.set(bean, value);
			}
		}
	}

// 方法赋值:
	@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			if (checkPropertySkipping(pvs)) {
				return;
			}
			Method method = (Method) this.member;
			Object[] arguments;
			if (this.cached) {
				// Shortcut for avoiding synchronization...
				arguments = resolveCachedArguments(beanName);
			}
			else {
				int argumentCount = method.getParameterCount();
				arguments = new Object[argumentCount];
				DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
				Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				for (int i = 0; i < arguments.length; i++) {
					MethodParameter methodParam = new MethodParameter(method, i);
					DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
					currDesc.setContainingClass(bean.getClass());
					descriptors[i] = currDesc;
					try {
						Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
						if (arg == null && !this.required) {
							arguments = null;
							break;
						}
						arguments[i] = arg;
					}
					catch (BeansException ex) {
						throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
					}
				}
				synchronized (this) {
					if (!this.cached) {
						if (arguments != null) {
							DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
							registerDependentBeans(beanName, autowiredBeans);
							if (autowiredBeans.size() == argumentCount) {
								Iterator<String> it = autowiredBeans.iterator();
								Class<?>[] paramTypes = method.getParameterTypes();
								for (int i = 0; i < paramTypes.length; i++) {
									String autowiredBeanName = it.next();
									if (beanFactory.containsBean(autowiredBeanName) &&
											beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
										cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
												descriptors[i], autowiredBeanName, paramTypes[i]);
									}
								}
							}
							this.cachedMethodArguments = cachedMethodArguments;
						}
						else {
							this.cachedMethodArguments = null;
						}
						this.cached = true;
					}
				}
			}
			if (arguments != null) {
				try {
					ReflectionUtils.makeAccessible(method);
					method.invoke(bean, arguments);//方法执行
				}
				catch (InvocationTargetException ex) {
					throw ex.getTargetException();
				}
			}
		}

2.3.2 循环依赖问题

在填充属性的时候会涉及到循环依赖的问题

> 导致循环依赖原因

  1. 由构造函数造成的循环依赖
  2. 通过setter方法注入,且是多例模式下可能导致内存溢出
  3. 通过setter方法注入,且是单例模式下可能导致内存溢出

> 解决方式

在Spring中只有第3种方式的循环依赖问题被解决,其他两种会报异常。

第1种构造方法注入的情况下,在new对象的时候就会堵塞住了,其实也就是"先有鸡还是先有蛋"的历史难题。

第2种setter方法(多例)的情况下,每一次getBean()时,都会产生一个新的Bean,如此反复下去就会有无穷无尽的Bean产生了,最终就会导致OOM问题的出现。

> 三级缓存

java 复制代码
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

	1.singletonobject 单例池 存放已完成初始化的bean
	//一级缓存(单例池,经过完成生命周期的对象会放入其中)
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
	
	 2.存放未完成初始化的但是已经实例化的bean
    //二级缓存(刚实例化还未初始化的原始对象会放入其中)
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    
	3.存放某个bean的beanfactory
    //三级缓存(存放创建某个对象的工厂)
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
	
	。。。。。。。。
}

2.4 initializeBean()概览

到此时,bean 已完成了如下两个重要工作

调用 createBeanInstance() 方法:完成 bean 的实例化工作

调用 populateBean() 方法:完成 bean 的属性填充注入工作

接下来就是进行初始化工作了,先上流程图,在看细节

java 复制代码
/**
	 * 初始化给定的bean实例,应用工厂回调以及init方法和BeanPostProcessors
	 *
	 * Initialize the given bean instance, applying factory callbacks
	 * as well as init methods and bean post processors.
	 * <p>Called from {@link #createBean} for traditionally defined beans,
	 * and from {@link #initializeBean} for existing bean instances.
	 * @param beanName the bean name in the factory (for debugging purposes)
	 * @param bean the new bean instance we may need to initialize
	 * @param mbd the bean definition that the bean was created with
	 * (can also be {@code null}, if given an existing bean instance)
	 * @return the initialized bean instance (potentially wrapped)
	 * @see BeanNameAware
	 * @see BeanClassLoaderAware
	 * @see BeanFactoryAware
	 * @see #applyBeanPostProcessorsBeforeInitialization
	 * @see #invokeInitMethods
	 * @see #applyBeanPostProcessorsAfterInitialization
	 */
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		// 如果安全管理器不为空
		if (System.getSecurityManager() != null) {
			// 以特权的方式执行回调bean中的Aware接口方法
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			// Aware接口处理器,调用BeanNameAware、BeanClassLoaderAware、beanFactoryAware
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		//如果mdb为null || mbd不是"synthetic"。一般是指只有AOP相关的prointCut配置或者Advice配置才会将 synthetic设置为true
		if (mbd == null || !mbd.isSynthetic()) {
			// 将BeanPostProcessors应用到给定的现有Bean实例,调用它们的postProcessBeforeInitialization初始化方法。
			// 返回的Bean实例可能是原始Bean包装器
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			//调用初始化方法,先调用bean的InitializingBean接口方法,后调用bean的自定义初始化方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			//捕捉调用初始化方法时抛出的异常,重新抛出Bean创建异常:调用初始化方法失败
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		//如果mbd为null || mbd不是"synthetic"
		if (mbd == null || !mbd.isSynthetic()) {
			// 将BeanPostProcessors应用到给定的现有Bean实例,调用它们的postProcessAfterInitialization方法。
			// 返回的Bean实例可能是原始Bean包装器
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		//返回包装后的Bean
		return wrappedBean;
	}

2.4.1 invokeAwareMethods() 方法

实现 Aware 接口用于让 bean 能拥有某些额外的感知能力

如果 bean 实现了 BeanNameAware 接口,则将 beanName 设置进去

如果 bean 实现了 BeanClassLoaderAware 接口,则将 ClassLoader 设置进去

如果 bean 实现了 BeanFactoryAware 接口,则将 beanFactory 设置进去

java 复制代码
private void invokeAwareMethods(String beanName, Object bean) {
		//如果 bean 是 Aware 实例
		if (bean instanceof Aware) {
			//如果bean是BeanNameAware实例
			if (bean instanceof BeanNameAware) {
				//调用 bean 的setBeanName方法
				((BeanNameAware) bean).setBeanName(beanName);
			}
			//如果bean是 BeanClassLoaderAware 实例
			if (bean instanceof BeanClassLoaderAware) {
				//获取此工厂的类加载器以加载Bean类(即使无法使用系统ClassLoader,也只能为null)
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					//调用 bean 的 setBeanClassLoader 方法
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			//如果bean是 BeanFactoryAware 实例
			if (bean instanceof BeanFactoryAware) {
				// //调用 bean 的 setBeanFactory 方法
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

2.4.2 applyBeanPostProcessorsBeforeInitialization() 方法(重点)

在 bean 初始化之前调用,可以改变 bean 的一些属性

java 复制代码
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		//初始化返回结果为existingBean
		Object result = existingBean;
		//遍历 该工厂创建的bean的BeanPostProcessors列表
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			// postProcessBeforeInitialization:在任何Bean初始化回调之前(如初始化Bean的afterPropertiesSet或自定义的init方法)
			// 将此BeanPostProcessor 应用到给定的新Bean实例。Bean已经填充了属性值。返回的Bean实例可能时原始Bean的包装器。
			// 默认实现按原样返回给定的 Bean
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			// 如果 current为null
			if (current == null) {
				//直接返回result,中断其后续的BeanPostProcessor处理
				return result;
			}
			//让result引用processor的返回结果,使其经过所有BeanPostProcess对象的后置处理的层层包装
			result = current;
		}
		//返回经过所有BeanPostProcess对象的后置处理的层层包装后的result
		return result;
	}

2.4.3 invokeInitMethods() 方法(重点)

Spring为 bean 提供了两种初始化的方式,第一种是实现 InitializingBean 接口调用 afterPropertiesSet() 方法来完成初始化,

第二种通过反射调用 init-method 指定的方法相比,效率相对低。但是 init-method 方式消除了对 Spring 的依赖

如果调用 afterPropertiesSet() 方法时出错,那么就不会调用 init-method 指定的方法了

java 复制代码
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		// InitializingBean:当Bean的所有属性都被BeanFactory设置好后,Bean需要执行相应的接口:例如执行自定义初始化,或者仅仅是检查所有强制属性是否已经设置好。
		// bean是InitializingBean实例标记
		boolean isInitializingBean = (bean instanceof InitializingBean);
		// isExternallyManagedInitMethod是否外部受管理的Init方法名
		// 如果bean是InitializingBean实例&&(mdb为null||'afterPropertiesSet'不是外部受管理的Init方法名)
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			// 如果是日志级别为跟踪模式
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			// 如果安全管理器不为null
			if (System.getSecurityManager() != null) {
				try {
					// 以特权方式调用 bean的 afterPropertiesSet 方法
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				// 调用bean的afterPropertiesSet方法
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		// 如果mbd不为null&&bean不是NullBean类
		if (mbd != null && bean.getClass() != NullBean.class) {
			// 获取mbd指定的初始化方法名
			String initMethodName = mbd.getInitMethodName();
			// 如果initMethodName不为null&&(bean不是InitializingBean实例&&'afterPropertiesSet'是初始化方法名)
			// &&initMethodName不是外部受管理的Init方法名
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				// 在bean上调用指定的自定义init方法
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd)
			throws Throwable {

		// 获取初始化方法名称
		String initMethodName = mbd.getInitMethodName();
		Assert.state(initMethodName != null, "No init method set");
		// 获取初始化方法
		Method initMethod = (mbd.isNonPublicAccessAllowed() ?
				BeanUtils.findMethod(bean.getClass(), initMethodName) :
				ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));

		if (initMethod == null) {
			if (mbd.isEnforceInitMethod()) {
				throw new BeanDefinitionValidationException("Could not find an init method named '" +
						initMethodName + "' on bean with name '" + beanName + "'");
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("No default init method named '" + initMethodName +
							"' found on bean with name '" + beanName + "'");
				}
				// Ignore non-existent default lifecycle methods.
				return;
			}
		}

		if (logger.isTraceEnabled()) {
			logger.trace("Invoking init method  '" + initMethodName + "' on bean with name '" + beanName + "'");
		}
		Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);

		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				ReflectionUtils.makeAccessible(methodToInvoke);
				return null;
			});
			try {
				AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
						() -> methodToInvoke.invoke(bean), getAccessControlContext());
			}
			catch (PrivilegedActionException pae) {
				InvocationTargetException ex = (InvocationTargetException) pae.getException();
				throw ex.getTargetException();
			}
		}
		else {
			try {
				ReflectionUtils.makeAccessible(methodToInvoke);
				// 反射执行
				methodToInvoke.invoke(bean);
			}
			catch (InvocationTargetException ex) {
				throw ex.getTargetException();
			}
		}
	}

2.4.4 applyBeanPostProcessorsAfterInitialization() 方法(重点)

postProcessAfterInitialization() 方法是 BeanPostProcessor 接口提供的方法,可以看到它是在 bean 初始化之后调用的,这时的 bean 已完成了实例化,属性填充注入,初始化的工作;可以认为是一个完整的 bean 已在 spring 容器中了,这个地方也是产生代理对象的地方 也就是AOP的入口

java 复制代码
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		//初始化结果对象为result,默认引用existingBean
		Object result = existingBean;
		//遍历该工厂创建的bean的BeanPostProcessors列表
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			//回调BeanPostProcessor#postProcessAfterInitialization来对现有的bean实例进行包装
			Object current = processor.postProcessAfterInitialization(result, beanName);
			//一般processor对不感兴趣的bean会回调直接返回result,使其能继续回调后续的BeanPostProcessor;
			// 但有些processor会返回null来中断其后续的BeanPostProcessor
			// 如果current为null
			if (current == null) {
				//直接返回result,中断其后续的BeanPostProcessor处理
				return result;
			}
			//让result引用processor的返回结果,使其经过所有BeanPostProcess对象的后置处理的层层包装
			result = current;
		}
		//返回经过所有BeanPostProcess对象的后置处理的层层包装后的result
		return result;
	}

2.4.5 registerDisposableBeanIfNecessary()

java 复制代码
	/**
	 * 将给定Bean添加到该工厂中的可丢弃Bean列表中,注册器可丢弃Bean接口和/或在工厂关闭时调用给定销毁方法(如果适用)。只适用单例
	 *
	 * Add the given bean to the list of disposable beans in this factory,
	 * registering its DisposableBean interface and/or the given destroy method
	 * to be called on factory shutdown (if applicable). Only applies to singletons.
	 * @param beanName the name of the bean
	 * @param bean the bean instance
	 * @param mbd the bean definition for the bean
	 * @see RootBeanDefinition#isSingleton
	 * @see RootBeanDefinition#getDependsOn
	 * @see #registerDisposableBean
	 * @see #registerDependentBean
	 */
	protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
		// 如果有安全管理器器,获取其访问控制上下文
		AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
		// 如果mbd不是Prototype作用域 && bean在关闭时需要销毁
		if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
			// 如果mbd是单例作用域
			if (mbd.isSingleton()) {
				// Register a DisposableBean implementation that performs all destruction
				// work for the given bean: DestructionAwareBeanPostProcessors,
				// DisposableBean interface, custom destroy method.
				// 注册一个一次性Bean实现来执行给定Bean的销毁工作:DestructionAwareBeanPostProcessors 一次性Bean接口,自定义销毁方法。
				// DisposableBeanAdapter:实际一次性Bean和可运行接口适配器,对给定Bean实例执行各种销毁步骤
				// 构建Bean对应的DisposableBeanAdapter对象,与beanName绑定到 注册中心的一次性Bean列表中
				registerDisposableBean(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
			else {
				// A bean with a custom scope...
				// 具有自定已作用域的Bean
				// 获取mdb的作用域
				Scope scope = this.scopes.get(mbd.getScope());
				// 如果作用域为null
				if (scope == null) {
					// 非法状态异常:无作用登记为作用名称'mbd.getScope'
					throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
				}
				// 注册一个回调,在销毁作用域中将构建Bean对应的DisposableBeanAdapter对象指定(或者在销毁整个作用域时执行,
				// 如果作用域没有销毁单个对象,而是全部终止)
				scope.registerDestructionCallback(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
		}
	}

2.4.6 补充:Spring中bean初始化的方式

一、ContextRefreshedEvent事件

ContextRefreshedEvent:是Spring容器初始化完成后调用的事件。

ContextRefreshedEvent的父类是ApplicationContextEvent,是一个事件。所以我们通过ApplicationListener来实现

java 复制代码
@Component
public class PersonAfterListener implements ApplicationListener<ContextRefreshedEvent> {
    @Autowired
    private Person person;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        person.run("ContextRefreshedEvent");
    }
}

二、PostConstruct 注解

PostConstruct注解修饰的方式,是在spring容器启动时运行的。优先级大于ContextRefreshedEvent事件。

java 复制代码
@Component
public class PersonAfterPostConstruct {
    @Autowired
    private Person person;

    @PostConstruct
    public void postConstruct(){
        person.run("PostConstruct");
    }
}

三、InitializingBean

InitializingBean是spring容器在启动并初始化好内部示例后调用的,用来最终为总体bean添加最后属性和操作。

java 复制代码
@Component
public class PersonAfterInitializingBean implements InitializingBean {
    @Autowired
    private Person person;

    @Override
    public void afterPropertiesSet() throws Exception {
        person.run("InitializingBean");
    }
}

四、init-method方法

这种方法有一定的局限性,并且可能会覆盖曾经的init操作,需要慎用。

Bean在加载到Spring容器中时需要先将Bean的定义信息抽象为BeanDefinition,其中有一个属性init-method代表将来Bean初始化时要调用的方法。

我们通过BeanFactoryPostProcessor来注入init-method方法,并且该方法必须是没有参数的。

java 复制代码
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class PersonAfterInit implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition person = beanFactory.getBeanDefinition("person");
        person.setInitMethodName("run");
    }
}

五 、实现 SmartInitializingSingleton 接口

SmartInitializingSingleton是Bean容器在初始化所有非懒加载的单例Bean后调用的方法。

java 复制代码
@Component
public class PersonAfterSmartInitializingSingleton implements SmartInitializingSingleton {
    @Autowired
    private Person person;

    @Override
    public void afterSingletonsInstantiated() {
        person.run("SmartInitializingSingleton");
    }
}

六、CommandLineRunner(仅限Spring Boot)

CommandLineRunner 是一个Spring boot 接口,在应用初始化后执行,且仅会执行一次。可以用来打印项目中配置文件的参数,方便排查问题。

java 复制代码
@Component
public class PersonAfterCommandLineRunner implements CommandLineRunner {
    @Autowired
    private Person person;

    @Override
    public void run(String... args) throws Exception {
        person.run("CommandLineRunner");
    }
}
相关推荐
蓝天星空23 分钟前
spring cloud gateway 3
java·spring cloud
罗政28 分钟前
PDF书籍《手写调用链监控APM系统-Java版》第9章 插件与链路的结合:Mysql插件实现
java·mysql·pdf
一根稻草君34 分钟前
利用poi写一个工具类导出逐级合并的单元格的Excel(通用)
java·excel
kirito学长-Java36 分钟前
springboot/ssm网上宠物店系统Java代码编写web宠物用品商城项目
java·spring boot·后端
海绵波波10743 分钟前
flask后端开发(9):ORM模型外键+迁移ORM模型
后端·python·flask
余生H1 小时前
前端Python应用指南(二)深入Flask:理解Flask的应用结构与模块化设计
前端·后端·python·flask·全栈
木头没有瓜1 小时前
ruoyi 请求参数类型不匹配,参数[giftId]要求类型为:‘java.lang.Long‘,但输入值为:‘orderGiftUnionList
android·java·okhttp
奋斗的老史1 小时前
Spring Retry + Redis Watch实现高并发乐观锁
java·redis·spring
high20111 小时前
【Java 基础】-- ArrayList 和 Linkedlist
java·开发语言
老马啸西风1 小时前
NLP 中文拼写检测纠正论文 C-LLM Learn to CSC Errors Character by Character
java