2023-09-16  阅读(42)
原文作者:王伟王胖胖 原文地址: https://blog.csdn.net/wangwei19871103/article/details/105142202

autowireResource自动装配Resource注解的对象

这里主要就是根据依赖描述进行工厂的解析,最后都是调用getBean(String name, Class<T> requiredType)方法,最后获取之后再注册到依赖映射里。其实这个有个resolveBeanByName,看起来好像是名字优先,其实也会获取类型的。

    	protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
    			throws NoSuchBeanDefinitionException {
    
    		Object resource;//自动装配的对象
    		Set<String> autowiredBeanNames;//自动装配的名字
    		String name = element.name;//依赖的属性名
    
    		if (factory instanceof AutowireCapableBeanFactory) {
    			AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
    			DependencyDescriptor descriptor = element.getDependencyDescriptor();//创建依赖描述
    			if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {//不包含依赖对象,或者依赖对象的bean定义,只能通过解析类型去处理
    				autowiredBeanNames = new LinkedHashSet<>();
    				resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
    				if (resource == null) {
    					throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
    				}
    			}
    			else {//获取依赖对象,里面就是getBean
    				resource = beanFactory.resolveBeanByName(name, descriptor);
    				autowiredBeanNames = Collections.singleton(name);//装配好的bean名字
    			}
    		}
    		else {
    			resource = factory.getBean(name, element.lookupType);
    			autowiredBeanNames = Collections.singleton(name);
    		}
    
    		if (factory instanceof ConfigurableBeanFactory) {
    			ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
    			for (String autowiredBeanName : autowiredBeanNames) {
    				if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {
    					beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);//注册依赖关系
    				}
    			}
    		}
    
    		return resource;
    	}

AutowiredAnnotationBeanPostProcessor的postProcessProperties

这里和前面的很像,都是这个模板。

    @Override
    	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    		try {
    			metadata.inject(bean, beanName, pvs);
    		}
    		catch (BeanCreationException ex) {
    			throw ex;
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    		}
    		return pvs;
    	}

InjectionMetadata的inject里面也是:

202309162313052891.png

AutowiredFieldElement的inject

但是最后是AutowiredFieldElement类型的方法,前面是ResourceElement的,他们都是InjectedElement的子类,ResourceElement把处理属性和方法放一起判断处理,自动装配的AutowiredFieldElementAutowiredMethodElement是分开处理的。

202309162313057512.png
如果有缓存依赖描述的话,会根据缓存的依赖描述来解析依赖对象,否则还是执行bean工厂的resolveDependency,但是这个时候会传入TypeConverter类型,解析出来之后如果是required的,就放入缓存,并注册依赖信息,如果自动装配的bean只有一个,创建ShortcutDependencyDescriptor,并放入缓存。

    @Override
    		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    			Field field = (Field) this.member;
    			Object value;
    			if (this.cached) {
    				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    			}
    			else {
    				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
    				desc.setContainingClass(bean.getClass());
    				Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
    				Assert.state(beanFactory != null, "No BeanFactory available");
    				TypeConverter typeConverter = beanFactory.getTypeConverter();
    				try {
    					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    				}
    				catch (BeansException ex) {
    					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
    				}
    				synchronized (this) {
    					if (!this.cached) {
    						if (value != null || this.required) {
    							this.cachedFieldValue = desc;
    							registerDependentBeans(beanName, autowiredBeanNames);
    							if (autowiredBeanNames.size() == 1) {
    								String autowiredBeanName = autowiredBeanNames.iterator().next();
    								if (beanFactory.containsBean(autowiredBeanName) &&
    										beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
    									this.cachedFieldValue = new ShortcutDependencyDescriptor(
    											desc, autowiredBeanName, field.getType());
    								}
    							}
    						}
    						else {
    							this.cachedFieldValue = null;
    						}
    						this.cached = true;
    					}
    				}
    			}
    			if (value != null) {
    				ReflectionUtils.makeAccessible(field);
    				field.set(bean, value);
    			}
    		}

AutowiredAnnotationBeanPostProcessor的resolvedCachedArgument

检查缓存是不是依赖描述类型的,是的话就取出相关数据,然后解析依赖。

    @Nullable
    	private Object resolvedCachedArgument(@Nullable String beanName, @Nullable Object cachedArgument) {
    		if (cachedArgument instanceof DependencyDescriptor) {
    			DependencyDescriptor descriptor = (DependencyDescriptor) cachedArgument;
    			Assert.state(this.beanFactory != null, "No BeanFactory available");
    			return this.beanFactory.resolveDependency(descriptor, beanName, null, null);
    		}
    		else {
    			return cachedArgument;
    		}
    	}

其实不管哪种注入的注解,原理都是一样的,都要根据名字和类型去容器里找,其他的类似的自己看下就好了。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文