(二)SpringBoot源码解析--自动注入过程 Autowired原理(1)

springboot 版本: 2.x
spring 版本 5.x

本篇文章主要分析下 Bean 属性的自动注入过程,并且会概要的分析下 Bean的实例化过程。

在上一篇文章中介绍了 springboot启动过程,其中也介绍了 bean的创建时机。其创建代码为 AbstractApplicationContext类refresh()方法中的如下代码:
image.png

Java bean 的初始化以及 field 的注入,都是通过这个方法完成的。

在这之前我们首先要熟悉几个类:
DefaultListableBeanFactory :默认的 bean工厂,看下这个类的继承结构:

image.png

AbstractAutowireCapableBeanFactory:负责创建 bean。
DefaultSingletonBeanRegistry:负责存储已经创建出来的 bean。
AutowiredAnnotationBeanPostProcessor: BeanPostProcessor的派生类, 会被 AbstractAutowireCapableBeanFactory调用并负责注入 bean 的属性。(BeanPostProcessor 的注册时机可以参考上一篇文章https://www.jianshu.com/p/5d75c9bdf0c6)

OK,一些必要的概念已经介绍完了,总结下DefaultListableBeanFactory本质上是一个容器,它会负责创建bean,存储 bean, 还会负责给 bean 注入属性。

接下来 , It’s show time.

AbstractApplicationContext finishBeanFactoryInitialization() 方法:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
               // 忽略代码。。。

		// Instantiate all remaining (non-lazy-init) singletons.
        //负责创建非懒加载的单例的bean
		beanFactory.preInstantiateSingletons();
	}

DefaultListableBeanFactory preInstantiateSingletons() 方法:

public void preInstantiateSingletons() throws BeansException {
	//  忽略代码。。。

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// 获取所有需要通过工程实例化的 bean 定义。
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//非抽象类, 并且是单例的, 并且是非懒加载的,才会创建
				if (isFactoryBean(beanName)) {
					//如果是 FactoryBean
                                        //忽略代码。。。
						
				}
				else {
                          //非 FactoryBean, 也就是我们的 controller、service、dao 等等。。 
                         //创建 bean
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable 
// 忽略代码
	}

进入 getBean 方法,一路跟踪下去

    @Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

进入 AbstractBeanFactory doGetBean()方法

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

		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		// 去缓存中获取 bean, 判断 bean 是否已经被创建
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			//忽略代码。。。。。
			
			//如果已经创建了,则直接将sharedInstance转为 bean, 一般情况下(service, controller...)这里的 bean 和sharedInstance指向的是同一个对象
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}  else {
			//如果此 bean 没有被创建,则执行下面常见 bean 的逻辑
			
			// 忽略代码。。。
			
			try {
			
				// 忽略代码。。。 话说 spring 的设计很精妙,但是代码实现确实不算优雅,一个方法太长了。。。。
				// Create bean instance.
				if (mbd.isSingleton()) {
				// 创建 bean, 这里用了 lamda表达式的匿名内部类的实现方式
				// 这个匿名内部类是ObjectFactory, 只有一个方法,getObject(), 其实先就是下面的代码
				// getSingleton()方法里面会调用 objectFactory.getObject()方法,实际执行的也就是createBean()方法。
					sharedInstance = getSingleton(beanName, () -> {
						try {
							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);
				}
				// 忽略代码。。。。
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}
   //忽略代码。。。
   
   
		return (T) bean;
	}

进入 createBean方法,即AbstractAutowireCapableBeanFactory类的 createBean() 方法

	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// 忽略一切。。。。
		try {
			//重点部分, 创建 bean
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isDebugEnabled()) {
				logger.debug("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

进入 doCreateBean()方法,也在AbstractAutowireCapableBeanFactory中。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
		//创建bean, 也就是会调用 bean 的构造方法。 注意,这个方法虽然实例化了 bean,但是并没有给 bean 注入属性
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		
		//忽略代码。。。
		
		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					// 这里会缓存每个 bean的定义,也就是会初始化 bean 的元数据,其中包括 bean 有哪些需要注入的属性,
					// 跟踪下去会发现其实调用的是AutowiredAnnotationBeanPostProcessor postProcessMergedBeanDefinition()方法
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}
	
	  //忽略代码。。。
	
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			// 将实例化好的 bean,添加至缓存,也就是DefaultSingletonBeanRegistry singletonFactories属性中,
			// singletonFactories是一个 map, key 是 beanName, value 是这个 bean 对应的工厂。
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			//此方法才是真正为 bean 注入属性的方法, 并且是递归注入,
			//依赖的是AutowiredAnnotationBeanPostProcessor ,这个类也是 BeanPostProcessor 的派生类。但是经过适配的,主要功能就是执行 autowired。
			//再注入属性实例的过程中,首先会去 DefaultSingletonBeanRegistry 缓存中判断实例是否初始化,如果已经初始化则直接赋值,否则执行上面一些列的 createBean, doCreateBean 方法实例化对象
			//因为实例化和注入是互相不依赖的, 所以即使出现循环依赖的情况: A 依赖 B, B 也依赖 A, 也不会出现问题。 
			//循环依赖的初始化过程如下,1. 初始化 A ; 2. 将 A 加入缓存;  3. 给 A 注入 B 对象; 4. 发现 B 没有初始化, 初始化 B.
			//5. 给 B 注入 A 对象,获取 A 时,发现A 再缓存中, 直接将 A 的实例赋值给B,支持 B 初始化且注入完成。 6. 将 B 的实例注入给 A。
			//至此 完成 A B 的初始化和注入。
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		
		// 忽略 忽略。。。。

		return exposedObject;
	}

最后我们来看下是如何找到需要注入的 Autowired 属性的,也就是
AutowiredAnnotationBeanPostProcessor postProcessMergedBeanDefinition()方法

@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}

进入findAutowiringMetadata()方法

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
		// Fall back to class name as cache key, for backwards compatibility with custom callers.
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// Quick check on the concurrent map first, with minimal locking.
//首先判断缓存中是否存在
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if (metadata != null) {
						metadata.clear(pvs);
					}
//如果不存在则新建元数据
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

进入buildAutowiringMetadata()方法

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
		Class<?> targetClass = clazz;

		do {
			final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();

//又是一个匿名内部类,不过首先是doWithLocalFields()方法通过反射机制找到所有的 field
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
			//再找到被 Autowired注解注释的 field
				AnnotationAttributes ann = findAutowiredAnnotation(field);
				if (ann != null) {
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					boolean required = determineRequiredStatus(ann);
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			//忽略代码。。。。
		}
		while (targetClass != null && targetClass != Object.class);

		return new InjectionMetadata(clazz, elements);
	}

进入 ReflectionUtils.doWithLocalFields();

public static void doWithLocalFields(Class<?> clazz, FieldCallback fc) {
		for (Field field : getDeclaredFields(clazz)) {
			try {
				fc.doWith(field);
			}
			catch (IllegalAccessException ex) {
				throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex);
			}
		}
	}


private static Field[] getDeclaredFields(Class<?> clazz) {
		Assert.notNull(clazz, "Class must not be null");
		Field[] result = declaredFieldsCache.get(clazz);
		if (result == null) {
			try {
//最终还是反射
				result = clazz.getDeclaredFields();
				declaredFieldsCache.put(clazz, (result.length == 0 ? NO_FIELDS : result));
			}
			catch (Throwable ex) {
				throw new IllegalStateException("Failed to introspect Class [" + clazz.getName() +
						"] from ClassLoader [" + clazz.getClassLoader() + "]", ex);
			}
		}
		return result;
	}

首先通过反射找到所有的 field,再区分出被 autowired注释的 field(本部分比较复杂,本文不做分析了),然后再通过反射给这些 field 的赋值(这部分也比较简单,就是 Invoke 一下 set方法)。bean 的注入就完成了。

还是有很多细节的部分没有分析到,但是面面俱到也不现实,重要是要知道其思想和大致原理。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值