spring源码:bean加载之创建bean-创建BeanWrapper

一、介绍

  BeanWrapper是对bean实例的一层包装,目前在spring中有四种实例化bean的方式,分别为:supplier、工厂方法、有参构造函数、无参构造函数。

二、bean加载流程

  1. 获取用户传入name对应的beanName
  2. 尝试从缓存中获取bean实例
  3. 缓存中不存在,加载bean实例
    3.1. 检查循环依赖
    3.2 处理parentBeanFactory
    3.3 处理依赖的bean(dependsOn)
    3.4 三种bean实例的创建
     3.4.1 单例bean的创建
      3.4.1.1 获取单例bean,getSingleton()方法
      3.4.1.2 准备创建bean,createBean()方法
      3.4.1.3 创建bean,doCreateBean()方法
       3.4.1.3.1 创建BeanWrapper(本章解析
     3.4.2 原型bean的创建
     3.4.3 根据scope策略创建bean
  4. 从bean实例中获取真正的对象
  5. 转换对象类型
  6. 返回对象实例

三、相关类及方法

  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance:创建bean实例整体流程的方法
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#obtainFromSupplier:supplier方式创建bean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#instantiateUsingFactoryMethod:使用工厂方法创建bean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor:有参构造方法创建bean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#instantiateBean:无参构造方法创建bean

四、创建beanWrapper的整体流程

	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// 1. 解析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());
		}

		// 2. 使用supplier方式初始化bean(方式一)
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		// 3. 使用工厂方法初始化bean(方式二)
		if (mbd.getFactoryMethodName() != null)  {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// 4. 使用构造函数创建bean
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				// 已解析出对应的构造函数
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		// 4.1 已解析出对应的构造函数
		if (resolved) {
			if (autowireNecessary) {
				// 有参构造函数初始化bean(方式三)
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				// 无参构造函数初始化bean(方式四)
				return instantiateBean(beanName, mbd);
			}
		}

		// 4.2 需要根据参数解析构造函数
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
			// 有参构造函数初始化bean
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// 无参构造函数初始化bean
		return instantiateBean(beanName, mbd);
	}

在这里插入图片描述
可以看到有四种(图中的粉色方块)方式可以创建bean实例,优先级为:initSupplier方式 > 工厂方法方式 > 无参构造函数方式 = 有参构造函数方式,其中无参、有参构造函数是根据条件来选择使用哪种方式创建bean实例的。下面来分别分析这四种方式

1. initSupplier方式创建bean:obtainFromSupplier(spring5.0新增)
1.1 使用方式
一般使用在用户注册自定义的BeanDefinition的场景中,这样对bean实例的初始化,增加了极大的灵活性。以往beanName基本都是写死在xml或者注解中的,有了initSupplier就可以设置通过计算得到的beanName、构造函数中的参数等等。

    @Test
    public void registerBeanDefinition() {
        // 1. 创建DefaultListableBeanFactory
        DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory(null);

        // 2. 通过BeanDefinitionBuilder把创建Person的方式设置到initSupplier
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Person.class,
            Person::new);

        // 3. 注册beanDefinition(beanName可灵活设置)
        defaultListableBeanFactory.registerBeanDefinition("supplierPerson",
            beanDefinitionBuilder.getBeanDefinition());

        // 4. 获取bean
        Object supplierPerson = defaultListableBeanFactory.getBean("supplierPerson");
        System.out.println(supplierPerson);
    }

第2步,可以通过initSupplier可灵活编写创建Person的代码;第3步,可灵活设置beanName。

除了DefaultListableBeanFactory有注册beanDefinition的方法,GenericApplicationContextSimpleBeanDefinitionRegistry两个类也有同样的功能。

1.2 initSupplier初始化bean源码

	protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
		String outerBean = this.currentlyCreatedBean.get();
		this.currentlyCreatedBean.set(beanName);
		Object instance;
		try {
			// 调用用户自定义的代码
			instance = instanceSupplier.get();
		}
		finally {
			if (outerBean != null) {
				this.currentlyCreatedBean.set(outerBean);
			}
			else {
				this.currentlyCreatedBean.remove();
			}
		}
		BeanWrapper bw = new BeanWrapperImpl(instance);
		initBeanWrapper(bw);
		return bw;
	}

这里我们看到,只是简单的调用了用户自定义的方法。

2. 工厂方法创建bean:instantiateUsingFactoryMethod
2.1 使用方式

  • 工厂类
public class MyFactory {

    public static Person staticMethod(String name, Integer age){
        System.out.println("静态工厂方法创建方式");
        return new Person(name, age);
    }

    public Person factoryMethod(String name, Integer age){
        System.out.println("普通工厂方法创建方式");
        return new Person(name, age);
    }
}
  • 配置(两种方式:实例方法和静态方法)
    <!--工厂方法为实例方法时,需要创建工厂实例-->
    <bean id="myFactory" class="com.kaka.spring.pojo.factory.MyFactory"/>
    <bean id="personByFactory" factory-bean="myFactory" factory-method="factoryMethod">
        <constructor-arg index="0" value="personByFactory"/>
        <constructor-arg index="1" value="22"/>
    </bean>

    <!--工厂方法为静态方法时,class指定为工厂类,直接使用静态方法即可-->
    <bean id="staticPerson" class="com.kaka.spring.pojo.factory.MyFactory" factory-method="staticMethod">
        <constructor-arg name="name">
            <value type="java.lang.String">staticPerson</value>
        </constructor-arg>
        <constructor-arg name="age" value="9"/>
    </bean>
  • 工厂方法为实例方法时,需要把工厂类配置为一个bean,然后对应的bean通过factory-bean指定该工厂类bean,factory-method指定创建bean使用的实例方法名称;
  • 工厂方法为静态方法时,仅需要配置一个factory-method指定创建bean使用的静态方法名称即可
  • 获取bean
	@Test
	public void factoryMethod(){
		// 1. 创建bean工厂
		Resource classPathResource = new ClassPathResource("applicationContext.xml");
		BeanFactory xmlBeanFactory = new XmlBeanFactory(classPathResource);
		
		// 测试获取bean(工厂方法为实例方法方式)
		Person personByFactory = xmlBeanFactory.getBean("personByFactory", Person.class);
		System.out.println(personByFactory);

		// 测试获取bean(工厂方法为静态方法方式)
		Person staticPerson = xmlBeanFactory.getBean("staticPerson", Person.class);
		System.out.println(staticPerson);

	}

3. 有参构造函数创建bean:autowireConstructor

	public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
			@Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) {

		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);

		Constructor<?> constructorToUse = null;
		ArgumentsHolder argsHolderToUse = null;
		Object[] argsToUse = null;

		// 1. 获取构造函数的参数:argsToUse
		// 1.1 explicitArgs通过getBean 方法传入
		// 如果getBean 方法调用调用的时候指定方法参数那么直接使用
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			// 如果在getBean 方法没有指定,则尝试从配置文件中解析
			Object[] argsToResolve = null;
			// 1.2 尝试从缓存中获取构造函数的参数
			synchronized (mbd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				// 构造函数已解析完成
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// 从RootBeanDefinition中取完全解析的构造函数参数
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						// 部分准备好的构造函数参数
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			// 如果缓存中存在
			if (argsToResolve != null) {
				// 解析缓存中的参数类型
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
			}
		}
		// 1.3 如果缓存中不存在确定的构造函数,需要解析构造函数和参数
		if (constructorToUse == null) {
			// Need to resolve the constructor.
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;

			int minNrOfArgs;
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				// 提取配置文件中配置的构造函数参数(解析BeanDefinition的时候提到过)
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				// 用于承载解析后的构造函数参数的值
				resolvedValues = new ConstructorArgumentValues();
				// 能解析到的参数个数
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}

			// Take specified constructors, if any.
			Constructor<?>[] candidates = chosenCtors;
			if (candidates == null) {
				Class<?> beanClass = mbd.getBeanClass();
				try {
					candidates = (mbd.isNonPublicAccessAllowed() ?
							beanClass.getDeclaredConstructors() : beanClass.getConstructors());
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Resolution of declared constructors on bean Class [" + beanClass.getName() +
							"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
				}
			}
			// 2. 确定构造函数
			// 排序给定的构造函数,public构造函数有限参数数量降序、非public构造函数参数数量降序
			AutowireUtils.sortConstructors(candidates);
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set<Constructor<?>> ambiguousConstructors = null;
			LinkedList<UnsatisfiedDependencyException> causes = null;

			for (Constructor<?> candidate : candidates) {
				Class<?>[] paramTypes = candidate.getParameterTypes();

				if (constructorToUse != null && argsToUse.length > paramTypes.length) {
					// 如果已经找到选用的构造函数或者需要的参数个数小于当前的构造函数参数个数则终止,
					// 因为已经按照参数个数降序排列了,后面肯定找不到了
					break;
				}
				if (paramTypes.length < minNrOfArgs) {
					// 参数个数不相等
					continue;
				}

				// 3. 参数持有者的确定
				ArgumentsHolder argsHolder;
				if (resolvedValues != null) {
					try {
						// 有参数则根据值构造对应参数类型的参数
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
						if (paramNames == null) {
							// 获取参数名称探索器
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								// 获取指定构造函数的参数名称
								paramNames = pnd.getParameterNames(candidate);
							}
						}
						// 3.1 根据名称和数据类型创建参数持有者
						argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
								getUserDeclaredConstructor(candidate), autowiring);
					}
					catch (UnsatisfiedDependencyException ex) {
						if (logger.isTraceEnabled()) {
							logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
						}
						// Swallow and try next constructor.
						if (causes == null) {
							causes = new LinkedList<>();
						}
						causes.add(ex);
						continue;
					}
				}
				else {
					// Explicit arguments given -> arguments length must match exactly.
					if (paramTypes.length != explicitArgs.length) {
						continue;
					}
					// 3.2 构造函数没有参数的情况
					argsHolder = new ArgumentsHolder(explicitArgs);
				}

				// 4. 探测是否有不确定性的构造函数存在,例如不同构造函数的参数为父子关系
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// 如果它代表着当前最接近的匹配则选择作为构造函数
				// Choose this constructor if it represents the closest match.
				if (typeDiffWeight < minTypeDiffWeight) {
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousConstructors = null;
				}
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet<>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}

			if (constructorToUse == null) {
				if (causes != null) {
					UnsatisfiedDependencyException ex = causes.removeLast();
					for (Exception cause : causes) {
						this.beanFactory.onSuppressedException(cause);
					}
					throw ex;
				}
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Could not resolve matching constructor " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
			}
			else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Ambiguous constructor matches found in bean '" + beanName + "' " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
						ambiguousConstructors);
			}

			if (explicitArgs == null) {
				// 将解析的构造函数加入缓存
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}

		try {
			// 5. 实例化策略
			final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();
			Object beanInstance;

			if (System.getSecurityManager() != null) {
				final Constructor<?> ctorToUse = constructorToUse;
				final Object[] argumentsToUse = argsToUse;
				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						strategy.instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse),
						beanFactory.getAccessControlContext());
			}
			else {
				// 实例化bean(见5)
				beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
			}
			// 将构建的实例加入BeanWrapper中
			bw.setBeanInstance(beanInstance);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean instantiation via constructor failed", ex);
		}
	}

以上代码比较长,但是要做的事情无非是确定构造函数和构造函数的参数。然后使用对应的实例化策略,来实例化bean。

4. 无参构造函数创建bean: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<Object>) () ->
						getInstantiationStrategy().instantiate(mbd, beanName, parent),
						getAccessControlContext());
			}
			else {
				// 实例化bean(见5)
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
			}
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}

5. 实例化策略

	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// 如果有需要覆盖或者动态替换的方法,则使用cglib进行动态代理,因为可以在创建代理的同时将动态方法织入类中
		// 但是如果没有需要动态改变的方法,为了方便直接反射就可以了
		// 如果不存在replace或者lookup的方法配置,
		if (!bd.hasMethodOverrides()) {
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					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<Constructor<?>>) clazz::getDeclaredConstructor);
						}
						else {
							constructorToUse =	clazz.getDeclaredConstructor();
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			// 直接反射实例化bean
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

		// cglib实例化bean
		public Object instantiate(@Nullable Constructor<?> ctor, @Nullable Object... args) {
			Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
			Object instance;
			if (ctor == null) {
				instance = BeanUtils.instantiateClass(subclass);
			}
			else {
				try {
					Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
					instance = enhancedSubclassConstructor.newInstance(args);
				}
				catch (Exception ex) {
					throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
							"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
				}
			}
			// SPR-10785: set callbacks directly on the instance instead of in the
			// enhanced class (via the Enhancer) in order to avoid memory leaks.
			Factory factory = (Factory) instance;
			factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
					new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
					new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
			return instance;
		}

如果用户没有使用replace或者lookup的配置,那么直接使用反射的方式。但如果使用了这两种方式,则需要使用cglib来把这些方法织入到实例的方法中了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章