Spring解密 - Bean 加载流程

栏目: Java · 发布时间: 6年前

内容简介:Spring解密 - Bean 加载流程

Spring 是一个开源的设计层面框架,解决了业务逻辑层和其他各层的松耦合问题,将面向接口的编程思想贯穿整个系统应用,同时它也是 Java工作中 必备技能之一…

前言

Spring解密 - XML解析 与 Bean注册 中,讲了 Bean的解析 ,本章将详细讲解 Spring中Bean的加载过程 ,相比 解析 而言,加载稍微复杂一点.

入口

public class Application {

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        Person person = context.getBean("person", Person.class);
        System.out.println(person.toString());
    }
}

重点分析 context.getBean();

解密

在分析 Bean 的加载过程前,我们看看 BeanFactory 的由来,以及 getBean 所属的类是谁。磨刀不误砍柴工

BeanFactory 的由来

1.查看 getBean() 的源码,此处的 getBeanFactory() 是怎么来的?

public class AbstractApplicationContext{

	@Override
	public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		// getBeanFactory() 是怎么来的?我们接着看
		return getBeanFactory().getBean(name, requiredType);
	}
}

2.应用程序的上下文

new ClassPathXmlApplicationContext("bean.xml"); 中,跳转到重载的构造方法中,我们会发现如下代码

public class ClassPathXmlApplicationContext {

	public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		// 解析 bean.xml 文件
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

}

它的目的是将普通路径解析为 类(classpath) 路径资源名称。 多个配置文件的情况下,后加载的 Bean 会覆盖先前定义好的 Bean ,这样做的目的是为了通过额外的XML文件来特意重写某个 Bean 这里我们可以看到调用了一个 refresh() ,它的作用是什么 呢?

3.初始化

刷新容器

public class AbstractApplicationContext {

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 准备刷新上下文
			prepareRefresh();
			// 通知子类,刷新内部 BeanFactory(创建 BeanFactory 的入口)
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
		}
	}

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 跟踪该方法
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

}

初次加载完 bean.xml 后,肯定会进入到 refresh() 方法中,这个时候会做容器初始化的工作,也就是 标签解析、Bean加载 等等工作,由于本章重点介绍 Bean加载 ,所以只贴了少量代码(看官莫急)

创建 DefaultListableBeanFactory

public class AbstractRefreshableApplicationContext {

	@Override
	protected final void refreshBeanFactory() throws BeansException {
		// 判断是否存在
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			// 创建 DefaultListableBeanFactory
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				// 然后赋值给 beanFactory 变量
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

	// 提取 BeanFactory
	@Override
	public final ConfigurableListableBeanFactory getBeanFactory() {
		synchronized (this.beanFactoryMonitor) {
			if (this.beanFactory == null) {
				throw new IllegalStateException("BeanFactory not initialized or already closed - " +
						"call 'refresh' before accessing beans via the ApplicationContext");
			}
			return this.beanFactory;
		}
	}
}

从上面的代码块中,我们可以看到 如果已经存在 beanFactory,将销毁旧的实例,然后在创建新的 DefaultListableBeanFactory ,最后 getBeanFactory() 就可以正常使用了。

Bean 加载

整个 Bean 的装载过程中,重点围绕 AbstractBeanFactory ,只要把它搞定剩下的就轻松了

public abstract class AbstractBeanFactory {

	@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		// 别名转换
		final String beanName = transformedBeanName(name);
		Object bean;

		// 检查缓存中是否存在 该 Bean 的单例(Bean默认的Scope = singleton)
		// 比如容器初始化的时候或者其他地方调用过getBean,已经完成了初始化
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			// 返回实例,FactoryBean 的情况下,并不是直接返回实例本身而是返回指定方法返回的实例
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// 存在循环依赖则报错
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// 判断工厂中是否含有当前 Bean 的定义
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// 如果没有,查询父工厂
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// 执行带有 args 参数的 getBean 方法
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// 如果没有参数,执行标准的 getBean 方法 
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			if (!typeCheckOnly) { // 如果不是做类型检查,则需要标记此 Bean 正在创建之中
				markBeanAsCreated(beanName);
			}

			try {
				// 将存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,如果BeanName是子Bean的话会合并父类的相关属性
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// 获取依赖的 Bean
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						getBean(dep);
					}
				}

				// 终于开始创建 Bean 实例了,如果是单例的,那么会创建一个单例的匿名工厂,
				// 如果是原型模式的,则不需要创建单例的工厂的,其他的如 request、session 作用域的,则根据自身的需要
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							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.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						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) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// 类型检查,如果不能进行类型转换,则抛出异常
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

}

整个代码块的内容还是不少的,接下来我们一步一步的分析。

转换 BeanName

final String beanName = transformedBeanName(name);

protected String transformedBeanName(String name) {
	return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

去除 FactoryBean 的修饰符,最终取指定 alias 所表示的 beanName 。因为有可能获取到以 & 开头的 FactoryBean ,所以要进行转化(关于 BeanFactory FactoryBean 后面会进行区分)

加载单例

检查缓存中是否存在 该 Bean 的单例 (Bean默认的Scope = singleton) ,如容器初始化的时候或者其他地方已经调用过 getBean() 完成了初始化

Object sharedInstance = getSingleton(beanName);

缓存加载 Bean

默认在装载 Bean 的时候会先去检查 singletonObjects 是否存在,如果存在直接提取缓存的。

public class DefaultSingletonBeanRegistry {

	/** 保存 BeanName 和创建 bean 实例之间的关系 bean name --> bean instance */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** 保存 BeanName 和创建 bean 实例的工厂之间的关系 bean name --> ObjectFactory */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** 保存 BeanName 和创建 bean 实例之间的关系 bean name --> bean instance */
	/** 与 singletonObjects 不同的是当一个单例 bean 被放到里面后,那么在 bean 在创建过程中,就可以通过 getBean 方法获取到,可以用来检测循环引用。 **/
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

	/** 保存当前所有已注册的 bean */
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 尝试从缓存获取实例
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				// 若该 bean 正在加载则不处理
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						// 存入到缓存中
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

}

构建实例(无缓存情况)

缓存中没有,那就当场构建一个 bean 出来,可以看到 getSingleton(String beanName, ObjectFactory<?> singletonFactory) 有两个参数,其中的 ObjectFactory 是怎么来的呢? 接着往下看

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    synchronized (this.singletonObjects) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            // 记录加载状态,,以便对循环依赖进行检测
            beforeSingletonCreation(beanName);
            singletonObject = singletonFactory.getObject();
            // 移除加载状态
            afterSingletonCreation(beanName);
            addSingleton(beanName, singletonObject);
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}

构建 ObjectFactory

此处与其说是构建 ObjectFactory ,不如说是在创建一个单例 Bean

if (mbd.isSingleton()) {
	sharedInstance = getSingleton(beanName, () -> {
		try {
			// 对 JDK8 lambda 表达式熟悉的小伙伴就不会陌生了
			return createBean(beanName, mbd, args);
		}
		catch (BeansException ex) {
			destroySingleton(beanName);
			throw ex;
		}
	});
	// 划重点了
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

创建 Bean

public class AbstractAutowireCapableBeanFactory {

	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

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

		// 首先判断需要创建的bean是否可以被实例化,这个类是否可以通过类装载器来载入。
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// 准备方法覆盖
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// 用 BeanPostProcessors 返回代理来替代真正的实例(如果 Bean 配置了 PostProcessor,那么这里返回的是一个代理)
			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 {
			// 重点来了
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isDebugEnabled()) {
				logger.debug("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException ex) {
			// A previously detected exception with proper bean creation context already...
			throw ex;
		}
		catch (ImplicitlyAppearedSingletonException ex) {
			// An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}


}

在创建 Bean 之前, Spring 还做了不少工作。

  • 判断创建的 bean 是否可以被实例化,这个类是否可以通过 ClassLoader 来载入,根据设置的 class 属性或根据 className 来解析 class
  • 对覆盖进行标记并验证,在 Spring 配置中存在 lookup-mothodreplace-method 的,这两个配置的加载时将配置统一存放在 BeanDefinition 中的 methodOverrides 属性里,这个方法的操作也是针对于这两个配置的;
  • 应用初始化前的后处理器,最后创建 bean 。在 createBean() 方法里执行完 resolveBeforeInstantiation 方法后,如果创建了代理且不为空的话就直接返回,否则需要进行常规 bean 的创建,这个创建过程是在 doCreateBean 中完成的

初始化 Bean

上面 createBean 交给了 doCreateBean 来创建 bean (上面还有一个重要的方法getObjectForBeanInstance,在后面分析)

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
		throws BeanCreationException {

	// 实例化 Bean
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		// 根据指定 bean 使用相应策略创建实例(正确情况会调用无参构造函数)
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	// 获取实例化好的 Bean(Person person = new Person()),此处还未进行赋值
	final Object bean = instanceWrapper.getWrappedInstance();
	// 获得实例化好的 class
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}

	// 记录创建 Bean 的 ObjectFactory,初始化前调用 post-processors,可以让我们在 bean 实例化之前做一些定制操作
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			try {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true;
		}
	}

	// 检测循环依赖,是否需要提早初始化(只能解决单例Bean)
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		if (logger.isDebugEnabled()) {
			logger.debug("Eagerly caching bean '" + beanName +
					"' to allow for resolving potential circular references");
		}
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	// 初始化bean实例。
	Object exposedObject = bean;
	try {
		// 在这个方法里面初始化对象,配置 xml 中的各种属性
		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);
		if (earlySingletonReference != null) {
			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) {
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
				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 " +
							"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
				}
			}
		}
	}

	// 用于销毁方法
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}

	return exposedObject;
}

上面源码完成的操作可以概括为以下几点

  • RootBeanDefinition 是不是单例,如果是单例先移除缓存
  • 实例化 bean ,将 RootBeanDefinition 转换为 BeanWrapper
  • 使用 MergedBeanDefinitionPostProcessor Autowired注解 就是通过此方法实现类型的预解析;
  • 解决循环依赖问题
  • populateBean() 中填充属性,配置在 XML 中的各种属性
  • 注册到 DisposableBean
  • 完成创建并返回 Bean 的实例

接下来我们看下 Spring 是如何创建 bean 实例的。跟踪 createBeanInstance() 方法

创建Bean实例

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
	// 获取 beanClass , 要先确保 Bean 是正确的,已经解析到当前节点了
	Class<?> beanClass = resolveBeanClass(mbd, beanName);

	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());
	}

	Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
	if (instanceSupplier != null) {
		return obtainFromSupplier(instanceSupplier, beanName);
	}

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

	// Shortcut when re-creating the same bean...
	boolean resolved = false;
	boolean autowireNecessary = false;
	if (args == null) {
		synchronized (mbd.constructorArgumentLock) {
			if (mbd.resolvedConstructorOrFactoryMethod != null) {
				resolved = true;
				autowireNecessary = mbd.constructorArgumentsResolved;
			}
		}
	}
	// 如果已经解析过则使用解析好的构造方法不需要再次锁定
	if (resolved) {
		if (autowireNecessary) {
			// 构造方法自动注入
			return autowireConstructor(beanName, mbd, null, null);
		}
		else {
			// 使用默认构造方法
			return instantiateBean(beanName, mbd);
		}
	}

	// 根据参数解析构造方法
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	if (ctors != null ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
		return autowireConstructor(beanName, mbd, ctors, args);
	}

	// 没有特殊处理的情况下,只需使用无参数的构造函数。
	return instantiateBean(beanName, mbd);
}

可以看出如果在 RootBeanDefinition 中存在 factoryMethodName 属性,或者说配置文件中配置了 factory-method ,那么 Spring 会尝试使用 instantiateUsingFactoryMethod(beanName, mbd, args) 方法根据 RootBeanDefinition 中的配置生成bean实例。然后再解析构造方法并进行实例化, Spring 会根据参数及类型判断使用哪个构造方法进行实例化。判断调用哪个构造方法的过程会采用缓存机制,如果已经解析过则不需要重复解析而是从 RootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 缓存的值去取,否则需再次解析。

populateBean 属性注入

这块代码比较多,有兴趣请自行跟进,就不贴出来了

populateBean 方法的中的主要处理流程:

  • InstantiationAwareBeanPostProcessor 处理器的 postProcessAfterInstantiation 方法控制程序是否继续填充属性;
  • 根据注入类型提取依赖的 bean ,并存入 PropertyValues 中;
  • InstantiationAwareBeanPostProcessor 处理器的 postProcessPropertyValues 方法对属性在填充前再次处理(主要还是验证属性);
  • 将所有 PropertyValues 中的属性填充到 BeanWrapper 中;

initializeBean 初始化Bean

学过 Spring 的都知道 bean 配置时有一个 init-method 属性,这个属性的作用是在 bean 实例化前调用 init-method 指定的方法进行需要的操作,现在就进入这个方法了; Spring 执行过 bean 的实例化,并且进行属性填充后,就会调用用户设定的初始化方法。

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
		// 特殊bean处理
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
		// 调用配置的 init-method
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

最后加载完 Bean 并执行完初始化操作后,一个 bean 的加载基本就结束了。

增强的 Bean

通过上面的描述,我们已经知道了一个的 Bean 是如何初始化的,已经具备普通 Bean 的功能。但是 Spring 还提供了一种增强的 Bean(FactoryBean) ,具备 factory 能力的 Bean ,这个能力主要在 getObjectForBeanInstance 得到。

public class AbstractBeanFactory {

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
	
		// 如果想要获取 FactoryBean 本身,那么 beanInstance 必须是 FactoryBean 的实例
		if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
		}
	
		// 如果 instance 不是 FactoryBean 实例,或者想要获取的就是 FactoryBean 实例,那么直接返回就好
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}
	
		Object object = null;
		if (mbd == null) {
			// 获取缓存的实例
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// 缓存中没有对象,那么从头准备 bean defition 实例化一个
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			// 在这里面获得最终的FactoryBean
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

}

关于 BeanFactoryFactoryBean 的区别:

  • BeanFactory: 容器的基本接口,是一个工厂,用来生产 Bean
  • FactoryBean: 是一个特殊的 Bean ,可以当作工厂使用的 Bean

循环依赖

上面有简单提到过 循环依赖(只有在单例情况下才会尝试解决循环依赖)。 无法解决就只能抛出 BeanCurrentlyInCreationException 异常

构造器循环依赖

无法解决,只能抛出 BeanCurrentlyInCreationException 异常

<bean id="A" class="com.battcn.A">
  <constructor-arg index="0" ref="B" />
</bean>
<bean id="B" class="com.battcn.B">
  <constructor-arg index="0" ref="C" />
</bean>
<bean id="C" class="com.battcn.C">
  <constructor-arg index="0" ref="A" />
</bean>

setter 循环依赖

Spring 容器提前暴露了刚好完成的构造器注入,但未完成其他步骤 ( 如 setter 注入bean )。 只能解决单例作用域的 bean 循环依赖。

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

prototype 范围的依赖处理

Spring 容器无法完成依赖注入,因为 Spring 容器不会缓存 prototype 作用域的 bean ,因此无法提前暴露一个创建中的 bean

<bean id="A" class="com.battcn.A" scope="prototype">
  <property name="B" ref="B" />
</bean>
<bean id="B" class="com.battcn.B" scope="prototype">
  <property name="C" ref="C" />
</bean>
<bean id="C" class="com.battcn.C" scope="prototype">
  <property name="A" ref="A" />
</bean>

总结

熬过几个无人知晓的秋冬春夏,撑过去一切都会顺着你想要的方向走…


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

UML参考手册

UML参考手册

兰博 / UML China / 机械工业出版社 / 2005-8 / 75.00元

《UML参考手册》在第1版的基础上进行了重大更新和扩展。UML的创建者James Rumbaugh、Ivar Jacobson和Grady Booch,清晰完整地讲述了UML的所有概念,包括对序列图、活动模型、状态机、组件、类和组件的内部结构以及特性描述的主要修订。手册式结构不仅有助于读者对UML的概念进行规范化的学习与理解,更为广大程序开发人员、系统用户和工程技术人员提供了方便快捷的查询方式。无......一起来看看 《UML参考手册》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

随机密码生成器
随机密码生成器

多种字符组合密码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码