Серия исходных кодов Spring: внедрение зависимостей (2) createBean

Java задняя часть Spring исходный код

существуетСерия исходных кодов Spring: внедрение зависимостей (1) (AbstractBeanFactory-getBean)Наконец, getBean является отправной точкой для внедрения зависимостей, а создание bean-компонентов выполняется с помощью createBean. Конкретная реализация createBean находится в AbstractAutowireCapableBeanFactory. В этой статье мы рассмотрим этот метод, чтобы увидеть процесс создания компонента.

Этот метод является центральным методом класса AbstractAutowireCapableBeanFactory, и его роль заключается в создании экземпляра компонента, заполнении экземпляра компонента, постобработке и т. д.

В createBean делаются три основные вещи:

  • Определите, можно ли создать экземпляр создаваемого компонента и можно ли загрузить класс через загрузчик классов.
  • Постпроцессор настроен на корреляционную обработку (если настроен, возвращает прокси)
  • Создать бин

В частности, посмотрите на метод:

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
	if (logger.isDebugEnabled()) {
		logger.debug("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.
	//判断需要创建的Bean是否可以实例化,这个类是否可以通过类装载器来载入
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// Prepare method overrides.
	try {
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		//异常:Validation of method overrides failed
	}

	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target 
		//bean instance.
		//是否配置了后置处理器相关处理(如果配置了则返回一个代理)
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	catch (Throwable ex) {
	    //异常:BeanPostProcessor before instantiation of bean failed
	}
    //创建Bean
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	if (logger.isDebugEnabled()) {
		logger.debug("Finished creating instance of bean '" + beanName + "'");
	}
	return beanInstance;
}

Как видно из приведенного выше кода, создание bean-компонента выполняется методом doCreateBean. Продолжайте смотреть на метод doCreateBean: (Это включает в себя интерфейс BeanWrapper, и друзья могут сделать шаг, чтобы узнать о "Серия источников Spring: BeanWrapper")

Код 1:

// 用BeanWrapper来持有创建出来的Bean对象
BeanWrapper instanceWrapper = null;
//如果是单例的话,则先把缓存中的同名bean清除
if (mbd.isSingleton()) {
	instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//实际创建的交给createBeanInstance来完成,
//bean的生成,这里会使用默认的类生成器,包装成BeanWrapperImpl类,
//为了下面的populateBean方法的属性注入做准备  
if (instanceWrapper == null) {
	instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;

Код 2:

Позволяет постпроцессорам изменять определения объединённых компонентов.

synchronized (mbd.postProcessingLock) {
    if (!mbd.postProcessed) {
    	try {
    		applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    	}
    	catch (Throwable ex) {
    	//异常:Post-processing of merged bean definition failed
    	}
    	mbd.postProcessed = true;
    }
    }

Код 3:

Кэшируйте синглтоны как можно скорее, чтобы иметь возможность разрешать циклические ссылки, даже если они инициируются интерфейсами жизненного цикла, такими как BeanFactoryAware.

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, new ObjectFactory<Object>() {
		@Override
		public Object getObject() throws BeansException {
			return getEarlyBeanReference(beanName, mbd, bean);
		}
	});
}

Код 4:

Это место, где инициализируется bean-компонент Обычно здесь происходит внедрение зависимостей: эта переменная экспонированного объекта хранит bean-компонент, который возвращается после завершения процесса инициализации по завершении внедрения зависимостей.

// Initialize the bean instance.
Object exposedObject = bean;
try {
	populateBean(beanName, mbd, instanceWrapper);
	if (exposedObject != null) {
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
}
catch (Throwable ex) {
    //抛出
	if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException)
	    ex).getBeanName())) {
		throw (BeanCreationException) ex;
	}
	else {
	//异常:Initialization of bean failed
	}
}

Код 5:

вот зарегистрированный бин

try {
	registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
    //异常处理
}
//返回结果
return exposedObject;

Вышеуказанные пять сегментов кода представляют собой логику обработки в doCreateBean, и заинтересованные партнеры могут самостоятельно проверить исходный код. Из вышеприведенного кода мы все равно не получаем конкретный процесс создания, потому что он зависит от doCreateBean:createBeanInstanceа такжеpopulateBeanдва метода.

существуетcreateBeanInstanceГенерируется объект Java, содержащийся в Bean. Давайте посмотрим, как он генерируется:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
	// 确保bean类实际上已经解析过了,可以实例化
	Class<?> beanClass = resolveBeanClass(mbd, beanName);

	if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
		//异常:Bean class isn't public, and non-public access not allowed:beanName
	}
     //1. 使用工厂方法来进行bean的实例化
	if (mbd.getFactoryMethodName() != null)  {
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}

	// 重新创建相同的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.需要确定构造函数...,使用构造函数进行bean实例化
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	if (ctors != null ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
		return autowireConstructor(beanName, mbd, ctors, args);
	}

	//3.没有特殊的处理:只需使用无参数构造函数。(默认构造函数)
	return instantiateBean(beanName, mbd);
}

Как видно из приведенного выше кода, существует множество различных способов генерации объектов, некоторые из них генерируются с помощью фабрики, а некоторые — с помощью функции автоподключения контейнера. Конечно, эти методы генерации определяются соответствующим BeanDefinition.

Один из наиболее распространенных способов настройки bean-компонентов в Spring — это XML-файлы и аннотации..

  • demo1
<bean id="user" class="com.glmapper.test.User">
  <property name="name" value="glmapper"></property>       
</bean>

Таким образом, назвав разрешения, предоставляемые классом, Spring может использовать механизм отражения для создания bean-компонента.

  • demo2
<bean id="user" class="com.glmapper.test.UserFactory" factory-method="getUser">
    <constructor-arg value="glmapper"></constructor-arg>           
</bean>

Это создается с помощью метода статической фабрики.Предоставленный класс является не именем разрешения класса, а полным именем класса статической фабрики, кроме того, метод получения bean-компонента (здесь getUser) и параметров (argument это glmapper).

  • demo3
<bean id="userFactory" class="com.glmapper.test.UserInstanceFactory">
    <!--用一个集合来保存我当前的对象实例-->
    <property name="map">
        <map>
            <entry key="user1">
                <bean class="com.glmapper.test.User">
                    <property name="name" value="glmapper1"></property>        
                </bean>
            </entry>    

            <entry key="user2">
                <bean class="com.glmapper.test.User">
                    <property name="name" value="glmapper2"></property>   
                </bean>
            </entry>
        </map>  
    </property>
 </bean>
 
 //实例1
 <bean id="user1" factory-bean="userFactory" factory-method="getUserInstance">
    <constructor-arg value="user1"></constructor-arg>           
 </bean>
//实例2
 <bean id="user2" factory-bean="userFactory" factory-method="getUserInstance">
    <constructor-arg value="user2"></constructor-arg>           
 </bean

Разница между этим методом и статической фабрикой заключается в том, что нам нужно создать экземпляр фабричного объекта, прежде чем мы сможем использовать этот фабричный объект для создания наших bean-компонентов. getUserInstance получает объект, который мы создали, через значение ключа (конечно, есть много способов, вот пример карты).关于注解的和使用FactoryBean接口的这里就暂时不说,后期再聊

Хорошо, давайте продолжим в течение нескольких минут. Выше было создано bean-компонента в фабричном методе. Конкретный исходный код немного длинный, поэтому я не буду помещать его здесь. Общая идея такая же, как и методы, упомянутые выше. . Далее, давайте посмотрим на общий код, который использует instanceiateBean (используя его конструктор по умолчанию) для создания bean-компонента:

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
	try {
		Object beanInstance;
		final BeanFactory parent = this;
	    //获取系统安全接口。
	    //如果已经为当前应用程序建立了安全管理器,则返回该安全管理器; 
	    //否则,返回null。
		if (System.getSecurityManager() != null) {
			beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					return getInstantiationStrategy().instantiate(mbd, beanName, parent);
				}
			}, getAccessControlContext());
		}
		else {
			beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
		}
		BeanWrapper bw = new BeanWrapperImpl(beanInstance);
		initBeanWrapper(bw);
		return bw;
	}
	catch (Throwable ex) {
		//异常:Instantiation of bean failed
	}
}

Видно, что вышеуказанное создание выполняется через:

getInstantiationStrategy().instantiate(mbd, beanName, parent);

Такой кусок кода сделан, да, здесь он близок к истине. Из семантического анализа сначала получается стратегия, а затем выполняется конкретизация с использованием текущей полученной стратегии. Хорошо, давайте посмотрим, что получает getInstantiationStrategy():

//返回实例化策略用于创建bean实例。
protected InstantiationStrategy getInstantiationStrategy() {
	return this.instantiationStrategy;
}
//默认的实例化测试是使用CGLIB代理
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

Видя это, мы видим, что в случае конструктора по умолчанию Cglib будет использоваться весной для создания экземпляров bean-компонентов (здесь cglib не будет повторяться). Давайте посмотрим на объявление класса CglibSubclassingInstantiationStrategy:

public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy 

Он наследуется от SimpleInstantiationStrategy, что это, черт возьми, такое?

SimpleInstantiationStrategy是Spring用来生成Bean对象的默认类,在这个类中提供了两种实例化java对象的方法,一种是基于java自身反射机制的BeanUtils,还有一种就是基于Cglib.

Как его создать говорить не буду, createBeanInstance на этом закончен (Бин создан), но он только создан, а Spring еще не обработал их, такие как свойства объекта бина, зависимости и так далее. Это еще один метод populateBean, упомянутый выше;

Этот метод на самом деле делает одну вещь: ** Заполняет экземпляр компонента в заданном BeanWrapper значениями свойств в определении компонента. ** Сегментированный вид: Следующий код предназначен для того, чтобы сначала инкапсулировать значение свойства, установленное в BeanDefinition, в PropertyValues, а затем определить, является ли наш BeanWrapper нулевым, если он нулевой, выдать исключение или пропустить текущий этап назначения пустого экземпляра.

//获取到BeanDefinition中设置的property值,封装成PropertyValues
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
	if (!pvs.isEmpty()) {
	//异常:Cannot apply property values to null instance
	}
	else {
	// Skip property population phase for null instance.
	    return;
	}
}

Смысл следующего кода в том, чтобы дать любому InstantiationAwareBeanPostProcessors возможность изменить состояние компонента перед установкой свойства.

boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
    	if (bp instanceof InstantiationAwareBeanPostProcessor) {
    		InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    		if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    			continueWithPropertyPopulation = false;
    			break;
    		}
    	}
    }
}

if (!continueWithPropertyPopulation) {
	return;
}

Ниже приводится обработка конкретного метода впрыска:

//处理autowire的注入;可以根据bean的名称和类型来注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
	mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

    // 则根据名称添加基于自动装配的属性值。
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
    	autowireByName(beanName, mbd, bw, newPvs);
    }
    
    // 根据类型添加基于自动装配的属性值。
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
    	autowireByType(beanName, mbd, bw, newPvs);
    }
    
    pvs = newPvs;
}

Два условия оценки, когда они выполняются, обрабатываются следующим образом:

  • Обрабатывает заданное значение свойства после того, как фабрика применила его к данному bean-компоненту. Позволяет проверить, удовлетворены ли все зависимости, например, на основе аннотации «Обязательно» в установщике свойств компонента. Также позволяет применять замену значений свойств, обычно путем создания новых экземпляров MutablePropertyValues ​​на основе исходных значений PropertyValues, добавления или удаления определенных значений.
  • выполнить проверку зависимости
//返回这个工厂是否拥有一个InstantiationAwareBeanPostProcessor
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//返回依赖检查代码。
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

if (hasInstAwareBpps || needsDepCheck) {
//从给定的BeanWrapper中提取一组已过滤的PropertyDescriptors,
//不包括在被忽略的依赖性接口上定义的被忽略的依赖类型或属性(译注)。
	PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
	if (hasInstAwareBpps) {
    	for (BeanPostProcessor bp : getBeanPostProcessors()) {
        	if (bp instanceof InstantiationAwareBeanPostProcessor) {
        		InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        		pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
        		if (pvs == null) {
        			return;
        		}
        	}
    	}
	}
	if (needsDepCheck) {
		checkDependencies(beanName, mbd, filteredPds, pvs);
	}
}

Наконец, введите свойства:

applyPropertyValues(beanName, mbd, bw, pvs);

Этот метод описывает процесс парсинга, а затем внедрения свойств; сначала проанализируйте объявление applyPropertyValues:

protected void applyPropertyValues(String beanName
, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs)
  • beanName имя компонента
  • MBD объединенное определение фана
  • BEANWRAPPER целевого объекта пакета BW
  • pvs новое значение атрибута

Фрагментация кода:

  • проверка параметров
if (pvs == null || pvs.isEmpty()) {
	return;
}
  • обработка параметров pvs
if (pvs instanceof MutablePropertyValues) {
    mpvs = (MutablePropertyValues) pvs;
    if (mpvs.isConverted()) {
    	// 使用预先转换后的值。
    	try {
    		bw.setPropertyValues(mpvs);
    		return;
    	}
    	catch (BeansException ex) {
    		//异常:Error setting property values
    	}
    }
    original = mpvs.getPropertyValueList();
    }
    else {
    original = Arrays.asList(pvs.getPropertyValues());
    }
  • valueResolver для разрешения BeanDefinition
BeanDefinitionValueResolver valueResolver = 
new BeanDefinitionValueResolver(this, beanName, mbd, converter);
  • Создает копию проанализированного значения и вводит в bean-компонент данные копии
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
  • Обработка обхода
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
    //返回此持有者是否已经包含转换后的值(true),还是需要转换值(false)。
    if (pv.isConverted()) {
    	deepCopy.add(pv);
    }   
    else {
    	String propertyName = pv.getName();
    	Object originalValue = pv.getValue();
    	//看下面的注释resolveValueIfNecessary
    	Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
    	Object convertedValue = resolvedValue;
    	boolean convertible = bw.isWritableProperty(propertyName) &&
    			!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
    	if (convertible) {
    		convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
    	}
    	// 可能将转换的值存储在合并的bean定义中,以避免为每个创建的bean实例重新转换。
    	if (resolvedValue == originalValue) {
    		if (convertible) {
    			pv.setConvertedValue(convertedValue);
    		}
    		deepCopy.add(pv);
    	}
    	else if (convertible && originalValue instanceof TypedStringValue &&
    			!((TypedStringValue) originalValue).isDynamic() &&
    			!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
    		pv.setConvertedValue(convertedValue);
    		deepCopy.add(pv);
    	}
    	else {
    		resolveNecessary = true;
    		deepCopy.add(new PropertyValue(pv, convertedValue));
    	}
    }
}
  • resolveValueIfNecessary

    Получив PropertyValue, вернуть значение, разрешая ссылки на другие bean-компоненты в фабрике, если это необходимо. значение может быть:

    • BeanDefinition, вызывающий создание соответствующего нового экземпляра компонента. Флаг Singleton и имена таких "внутренних компонентов" игнорируются: внутренние компоненты являются анонимными прототипами.
    • RuntimeBeanReference (должен быть разрешен)
    • ManagedList
    • ManagedSet
    • ManagedMap
    • Простой объект или нуль, в данном случае он потерян.

В следующем коде происходит внедрение зависимостей, которое фактически выполняется в BeanWrapperImpl.

try {
    bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
    //异常:Error setting property values
}

Как было сказано выше, Spring парсит BeanDefinition через BeanDefinitionValueResolver, а затем внедряет его в свойство, этот процесс будет рассмотрен в следующей статье.

欢迎关注微信公众号