[spring源码阅读]Sping Container中bean的实例化

287 阅读4分钟

Spring framework version:5.1.4 RELEASE
Spring Container在启动时, 会将配置中的bean进行实例化. 具体进行实例化操作的地方就是AbstractAutowireCapableBeanFactory.createBeanInstance().

AbtractAutowireCapableBeanFacotry.createInstance()

在createInstance()根据不同的bean-definition采取不同的实例化策略:

  1. facotry-method(工厂方法实例化)
  2. constructor autowiring(构造函数注入实例化)
  3. simple instantiate(简单实例化,默认无参构造函数实例化)
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		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());
		}

            // ?? jdk 1.8提供的函数编程Supplier来进行实例化
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

            // 1. 使用工厂方法进行实例化
		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);
			}
		}
            // 2. 使用构造函数自动注入方式实例化
		// 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);
		}

            // 3. 简单实例化,使用默认构造函数
		// No special handling: simply use no-arg constructor.
		return instantiateBean(beanName, mbd);
	}

通过阅读上面的源码,可以了解到spring提供了3种实例化的策略. 下面就讨论3种实例化策略具体怎么实现的.(ps:jdk 1.8提供的函数式编程Supplier方式进行的实例化放在文章最后讨论)

BeanWrapper??
AbstractAutowireCapableBeanFactory和实例化策略InstantiateStrategy的类图:

可以看到AbstractAutowireCapableBeanFactory中3中实例化策略最终都是交给instantiateStrategy:CglibSubclassingInstantiateStrategy类实现的.
ConstructResolver只是完成了一些辅助工作.

InstantiateStrategy Bean实例化策略
instantiate no-args constrcutor流程图

instantiate via given constrcutor流程图

instantiate via given factory-method流程图

@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			@Nullable Object factoryBean, final Method factoryMethod, Object... args) {

		try {
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					ReflectionUtils.makeAccessible(factoryMethod);
					return null;
				});
			}
			else {
				ReflectionUtils.makeAccessible(factoryMethod);
			}

			Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
			try {
				currentlyInvokedFactoryMethod.set(factoryMethod);
				// factoryMethod.invoke反射得到实例化bean
				Object result = factoryMethod.invoke(factoryBean, args);
				if (result == null) {
					result = new NullBean();
				}
				return result;
			}
			finally {
				if (priorInvokedFactoryMethod != null) {
					currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
				}
				else {
					currentlyInvokedFactoryMethod.remove();
				}
			}
		}
		catch (IllegalArgumentException ex) {
			throw new BeanInstantiationException(factoryMethod,
					"Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
					"args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
		}
		catch (IllegalAccessException ex) {
			throw new BeanInstantiationException(factoryMethod,
					"Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
		}
		catch (InvocationTargetException ex) {
			String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
			if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
					((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
				msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
						"declaring the factory method as static for independence from its containing instance. " + msg;
			}
			throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
		}
	}

Object result = factoryMethod.invoke(factoryBean, args);反射调用工厂方法获取bean实例. 如果工厂方法是要实例化bean中的静态工厂方法, 此时factoryBean=null,也可以反射调用类的静态方法. 在ConstructResolver中也有相关的设值.

		Object factoryBean;
		Class<?> factoryClass;
		boolean isStatic;

		String factoryBeanName = mbd.getFactoryBeanName();
		if (factoryBeanName != null) {
			if (factoryBeanName.equals(beanName)) {
				throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
						"factory-bean reference points back to the same bean definition");
			}
			factoryBean = this.beanFactory.getBean(factoryBeanName);
			if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
				throw new ImplicitlyAppearedSingletonException();
			}
			factoryClass = factoryBean.getClass();
			isStatic = false;
		}
		else {
			// It's a static factory method on the bean class.
			if (!mbd.hasBeanClass()) {
				throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
						"bean definition declares neither a bean class nor a factory-bean reference");
			}
			// 如果是要实例化的类的静态工厂方法,factoryBean=null
			factoryBean = null;
			factoryClass = mbd.getBeanClass();
			isStatic = true;
		}
Supplier实例化策略

在AbstractAutowireCapableBeanFactory中采用Supplier<?>来进行实例化的代码:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // resovle bean class ...
    
    // strategy: supplier<?>
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }
    
    // strategy: factory-method...
    // strategy: autowire-constructor...
    // strategy: simple instante: default no-args constructor
}

Supplier<?>jdk1.8中添加的函数式编程新特性, 在学习之前最好对jdk 1.8函数式编程有一定的了解.
Supplier<?>spring创建实例和factory-method实现的效果差不多,只是另外一种编程方式的实现.

AbstractBeanDefinition.setInstanceSupplier()
/**
	 * Specify a callback for creating an instance of the bean,
	 * as an alternative to a declaratively specified factory method.
	 * <p>If such a callback is set, it will override any other constructor
	 * or factory method metadata. However, bean property population and
	 * potential annotation-driven injection will still apply as usual.
	 * @since 5.0
	 * @see #setConstructorArgumentValues(ConstructorArgumentValues)
	 * @see #setPropertyValues(MutablePropertyValues)
	 */
	public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
		this.instanceSupplier = instanceSupplier;
	}

在官方源码注释中也说道Supplier<?>方式是对XML-Config <bean id='' factory-method='' class=''/>的一种替代方案
Specify a callback for creating an instance of the bean, as an alternative to a declaratively specified factory method.

Supplier<?>注册bean使用方式:

Example:
    //using registerBean(beanClass, beanSupplier,  customizers)
    public static void main(String[] args) {
        GenericApplicationContext gac = new GenericApplicationContext();
        gac.registerBean(LogService.class, LogService.LogServiceImpl::new,
                Customizers::lazy, Customizers::defaultInitMethod);
        gac.refresh();
        System.out.println("context refreshed");
        LogService ls = gac.getBean(LogService.class);
        ls.log("msg from main method");
        gac.close();
    }

LogService.LogServiceImpl::new 就是一个Supplier

Spring在创建bean的时候如何保证beanClass已经被加载进来
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
	// Make sure bean class is actually resolved at this point.
	Class<?> beanClass = resolveBeanClass(mbd, beanName);
	
	// actual create bean instance
	....
}

resolveBeanClass(mbd,beanName)确保了在创建bean实例的时候,bean对应的Class已经加载进来. 在resolveBeanClass(mbd,beanName)中针对不同的情况使用了Class.forName(className)classLoader.loadClass(className)来对beanClass进行加载.

Question: Class.forName(className)classLoader.loadClass(className)的类加载有什么不同? A: 两者都能完成对类Class的加载. Class.forName(className)加载进来的Class是已经完成初始化的; 而classLoaader.loadClass(className)则是没有进行初始化的.
例如: 数据库驱动中的初始化代码

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

通过Class.forName('com.mysql.jdbc.Driver') 加载数据库驱动类,会完成com.mysql.jdbc.Driver中的static静态初始化代码块. 这样我们才能后面使用DriverManager.getDriver(url)来获取到对应的数据库驱动进行连接.
使用classLoader.loadClass(className)仅加载Class对象到内存, 不负责初始化. 所以在数据库驱动类的加载中不适合使用classLoader.loadClass(className)来加载数据库驱动类.