青烟

小燕归园花正语,水清不问旧消息。

Spring源码 - Bean的依赖注入和查找

/**
 * 一个单例bean的依赖注入和查找
 */
public class SingletonBeanInjectLock {
    public static void main(String[] args) {
        // 创建Ioc容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        // 定义初始化类
        beanDefinition.setBeanClass(Person.class);
        // 用构造函数的方式初始化类
        ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
        constructorArgumentValues.addGenericArgumentValue("张三");
        constructorArgumentValues.addGenericArgumentValue("北京");
        constructorArgumentValues.addGenericArgumentValue(14212123);
        beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
        //将beanDefinition注册到容器中
        beanFactory.registerBeanDefinition("person",beanDefinition);

        System.out.println(beanFactory.getBean("person"));
    }

}

这里我们直接定义了一个实例,采用手动注册的方式将bean对象注入到ioc容器中。我们来看这段代码在源码中具体做了哪些事情。

第一步创建DefaultListableBeanFactory对象这个就不用说了,看下面的GenericBeanDefinition。之前我们说过beanDefinition是spring中bean对象的描述类,包含一些bean对象的配置信息。比如像作用域啊,bean对象的类、构造函数、init-method、工厂类之类的。

这里我们创建了一个GenericBeanDefinition,并且将他的类设置为Person,并且设置了它的构造函数的参数,用构造函数初始化Bean对象。然后通过registerBeanDefinition注册到容器中。

这里的注入具体干了什么事情呢?

	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		// 根据beanName查看是否已经有该bean对象存在
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
			// 将之前的beanDefinition覆盖掉
            // (这里删除了部分代码,实际上容器有个allowBeanDefinitionOverriding信息
            // 默认为true,如果不为true不会进行覆盖操作)
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
            // 这里是判断当前是否已经有bean被创建了,如果有的话,需要加锁来保障线程安全
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
                    // 保存该beanDefinition
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
                    // 从手动注册的bean类表中删除
					removeManualSingletonName(beanName);
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}
		
        // 如果当前已经有缓存的beanDefinition,则重置beanDefinition
		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
		else if (isConfigurationFrozen()) {
             // 清空allBeanNamesByType、singletonBeanNamesByType缓存信息
			clearByTypeCache();
		}
	}

这样就把bean对象存到了Ioc容器中。那么当我们调用getBean时做了什么呢?

	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

		String beanName = transformedBeanName(name);
		Object bean;

		// 查看当前是否是单例Bean对象
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			// 从缓存中获取单例Bean对象
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// 找到对应的BeanDefinition对象
			BeanFactory parentBeanFactory = getParentBeanFactory();
            // 类似双亲委派机制,先找父容器中是否有,优先从父容器中获取bean信息
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}
			
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
                
                // 这里可以有些疑问,什么是MergedBeanDefinition?
                // 实际上之前我们在DefaultListableBeanFactory注册成功之后,
                // 把对应的beanDefinition存到beanDefinitionMap中了。
                // 但是在AbstractBeanFactory中有个mergedBeanDefinitions,
                // 我们最终取的BeanDefinition也是从mergedBeanDefinitions中取的,
                // 所以我们需要合并到mergedBeanDefinitions中。
                // 这个地方做的事情就是如果当前这个BeanDefinition需要合并,就放到
                // mergedBeanDefinitions中,再返回该对象。
                
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
                // 查找依赖,并将依赖实例化
				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);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// Create bean instance.
                // 创建bean实例
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
                            // 这个方法实际上是写在AbstractAutowireCapableBeanFactory类中的
                            // 待会再看
							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 {
                        // 跟上面的isPrototypeCurrentlyInCreation对应
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
                    // 这个地方是给其他作用域用的 比如RequestScope、SessionScope
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName)) {
						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
					}
					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, () -> {
                            // 跟上面的isPrototypeCurrentlyInCreation对应
							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;
			}
		}

	
		return (T) bean;
	}

spring创建对象的类:
实际上最后是InstantiationStrategy决定用哪种策略去创建初始化bean对象。
image.png

一共是两种,上面的SimpleInstantiationStrategy直接就用的Java反射。CglibSubclassingInstantiationStrategy采用cglib生成类方式,实例化对象。

posted @ 2021-09-06 10:50  今后  阅读(304)  评论(1编辑  收藏  举报