栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring IOC源码系列(六):bean实例化的过程

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring IOC源码系列(六):bean实例化的过程

上篇提到bean的生成就是在AbstractAutowireCapableBeanFactory#doCreateBean方法中:

  • createBeanInstance(beanName, mbd, args),实例化;
  • populateBean(beanName, mbd, instanceWrapper),填充属性;
  • initializeBean(beanName, exposedObject, mbd),初始化;

这篇就来看下实例化的具体过程。

  • AbstractAutowireCapableBeanFactory#createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// 确保Class文件有被加载
		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());
		}

		// 工厂方法实例化bean,也就是我们配置的factory-method这个属性
		// 会调用我们配置的factory-method方法来实例化这个bean
		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);
			}
		}

		// Candidate constructors for autowiring?
		Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		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.
		return instantiateBean(beanName, mbd);
	}

这个方法主要是做了一些校验,然后处理了我们配置的工厂方法,简单来说就是我们可以通过factory-method属性来配置一个产生bean的工厂方法,在方法instantiateUsingFactoryMethod中,调用这个工厂方法来实例化相应的bean,如果不是这样方式的话,那就会调用构造方法来实例化bean。

  • AbstractAutowireCapableBeanFactory#instantiateBean
	protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
		try {
			Object beanInstance;
			final BeanFactory parent = this;
			if (System.getSecurityManager() != null) {
				beanInstance = AccessController.doPrivileged((PrivilegedAction) () ->
						getInstantiationStrategy().instantiate(mbd, beanName, parent),
						getAccessControlContext());
			}
			else {
				// 主要是这里,实例化的地方
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
			}
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			// 这个方法里面会设置之前提过的conversionService,用来做变量类型转换的配置
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}
 

这个方法没什么好说的,接着看吧。

  • SimpleInstantiationStrategy#instantiation
	@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// 如果没有方法覆盖就用Java的反射进行实例化,否则用cglib
		if (!bd.hasMethodOverrides()) {
			Constructor constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					// 获得Class对象
					final Class clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							constructorToUse = AccessController.doPrivileged(
									(PrivilegedExceptionAction>) clazz::getDeclaredConstructor);
						}
						else {
						    // 获取构造方法
							constructorToUse = clazz.getDeclaredConstructor();
						}
						// 属性设置,这个属性很多地方都会用到,当这个Bean第二次实例化的时候就直接用这个属性了
						// 在createBeanInstance方法里都有用到
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			// 就是反射调用了,就不看了
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// CGLIB,因为Java反射是不支持生成子类的bean的,所以如果存在方法覆盖时,只能用CGLIB来生成子类的bean
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

在这个方法中可以看到,实例化本质就是用了反射来生成bean对象,通过class对象来获取构造方法,然后调用newInstance方法来创建一个对象,实例化一个bean。而如果有方法覆盖的话,还需要用到CGLIB。
到这里,整个实例化bean的过程就看完了,只要抓住它的本质就是根据BeanDefinition信息来生成对应的bean就比较容易了:

  • BeanDefinition对象获取class对象;
  • class对象获取构造方法;
  • 构造方法调用newInstance方法来创建对象。
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号