国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring @Autowired 注解原理

這篇具有很好參考價值的文章主要介紹了Spring @Autowired 注解原理。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Spring @Autowired 注解原理

1.@Autowired 使用

@ComponentScan("org.example.bean")
public class AnnoContextDemo {

    @Autowired
    private User user;


    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnoContextDemo.class);

        User user1 = context.getBean(AnnoContextDemo.class).user;

        System.out.println("user1 = " + user1);
    }


}

被掃描的組件配置類

@Configuration
public class BeanConfig {

    @Bean
    public User user(){
        return new User(21,"張三");
    }

}

輸出結(jié)果

user1 = User{age=21, name='張三'}

2.依賴自動注入原理

定位@Autowired所在包 org.springframework.beans.factory.annotation.Autowired

找到同包下 AutowiredAnnotationBeanPostProcessor

Spring @Autowired 注解原理,spring,java,后端

AutowiredAnnotationBeanPostProcessor 的類繼承圖如下

Spring @Autowired 注解原理,spring,java,后端

AutowiredAnnotationBeanPostProcessor實現(xiàn)了InstantiationAwareBeanPostProcessor與

MergedBeanDefinitionPostProcessor兩個BeanPostProcessor后置處理器接口

  1. MergedBeanDefinitionPostProcessor 此接口主要有兩個方法 抽象方法 postProcessMergedBeanDefinition 默認方法 resetBeanDefinition

  2. InstantiationAwareBeanPostProcessor 此接口 抽象方法 postProcessBeforeInstantiation ,postProcessAfterInstantiation ,默認方法 postProcessProperties ,默認過時方法 postProcessPropertyValues

想搞清楚@Autowried注入原理,先得知道這些接口對應(yīng)方法執(zhí)行的先后順序 跟蹤ApplicationContext.refresh方法,調(diào)用鏈路如下

ApplicationContext.refresh() -> AbstractApplicationContext.finishBeanFactoryInitialization() -> ConfigurableListableBeanFactory.preInstantiateSingletons() - > AbstractBeanFactory.getBean() -> AbstractBeanFactory.doGetBean() -> AbstractBeanFactory.getSingleton() -> AbstractBeanFactory.createBean()

實例化前

-> resolveBeforeInstantiation() 執(zhí)行 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()前置方法 如果返回不為null,將執(zhí)行 InstantiationAwareBeanPostProcessor.postProcessAfterInitialization()后置方法。

創(chuàng)建bean實例階段

-> doCreateBean() -> createBeanInstance 反射創(chuàng)建bean實例

-> applyMergedBeanDefinitionPostProcessors() 執(zhí)行 MergedBeanDefinitionPostProcessor.MergedBeanDefinitionPostProcessor方法 合并bean定義信息

屬性注入階段

-> populateBean() -> 執(zhí)行 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 后置處理方法 -> 執(zhí)行InstantiationAwareBeanPostProcessor.postProcessProperties -> InstantiationAwareBeanPostProcessor.postProcessPropertyValues -> applyPropertyValues 執(zhí)行屬性注入

初始化階段

-> initializeBean() -> BeanPostProcessor.postProcessBeforeInitialization() 執(zhí)行前置方法 -> invokeInitMethods() 反射調(diào)用初始化方法 -> BeanPostProcessor.postProcessAfterInitialization 執(zhí)行后置方法

收尾注冊bean

->registerDisposableBeanIfNecessary() 注冊bean

通過上面追蹤refresh()方法我們可知,spring容器將先調(diào)用 AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition方法,然后執(zhí)行 postProcessProperties 方法

3. postProcessMergedBeanDefinition 查找需要自動注入的字段或方法

	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);
					}
					//查找類的字段,方法,是否有需要自動注入對象的元素,封裝InjectionMetadata
					metadata = buildAutowiringMetadata(clazz);
					//放入緩存中,供后面調(diào)用取出
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

進入 buildAutowiringMetadata 方法

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
		//判斷當前類是否有使用autowiredAnnotationTypes容器中的注解
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}

		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;

		do {
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
			//反射遍歷類中所有字段
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				//字段上是否有標注自動裝配相關(guān)的注解
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					boolean required = determineRequiredStatus(ann);
					//封裝InjectionMetadata
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});
			
			//反射遍歷類中所有方法
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
					//方法上是否有標注自動裝配相關(guān)的注解
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					if (method.getParameterCount() == 0) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					boolean required = determineRequiredStatus(ann);
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					//封裝InjectionMetadata
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});

			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

		return InjectionMetadata.forElements(elements, clazz);
	}

this.autowiredAnnotationTypes 為set集合,容器內(nèi)為需要自動注入的注解類

private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
	public AutowiredAnnotationBeanPostProcessor() {
	## 1.@Autowired
		this.autowiredAnnotationTypes.add(Autowired.class);
  ## 2.@Value
		this.autowiredAnnotationTypes.add(Value.class);
		try {
 ## 3.@javax.inject.Inject  JSR-330規(guī)范中定義的一個注解
			this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
			logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

4.postProcessProperties 需要自動注入的元素從容器中獲取bean后注入

	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;
	}

進入 metadata.inject() 方法

	public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
		Collection<InjectedElement> checkedElements = this.checkedElements;
		Collection<InjectedElement> elementsToIterate =
				(checkedElements != null ? checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
			//遍歷需要注入的元素
			for (InjectedElement element : elementsToIterate) {
				//不同類型調(diào)用各自inject方法
				element.inject(target, beanName, pvs);
			}
		}
	}

字段處理邏輯

通過 resolveFieldValue 方法,找到需要依賴的bean(單個或集合),通過 Filed.set方法注入

		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				try {
					value = resolvedCachedArgument(beanName, this.cachedFieldValue);
				}
				catch (NoSuchBeanDefinitionException ex) {
					// Unexpected removal of target bean for cached argument -> re-resolve
					value = resolveFieldValue(field, bean, beanName);
				}
			}
			else {
			//查找依賴的bean
				value = resolveFieldValue(field, bean, beanName);
			}
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				//反射設(shè)置值
				field.set(bean, value);
			}
		}

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}

			Class<?> type = descriptor.getDependencyType();
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String) {
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ?
							getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				try {
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				}
				catch (UnsupportedOperationException ex) {
					// A custom TypeConverter which does not support TypeDescriptor resolution...
					return (descriptor.getField() != null ?
							converter.convertIfNecessary(value, type, descriptor.getField()) :
							converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
				}
			}
		
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

			//字段非集合類型時bean時查找方法
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;

			if (matchingBeans.size() > 1) {
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					}
					else {
						// In case of an optional Collection/Map, silently ignore a non-unique case:
						// possibly it was meant to be an empty collection of multiple regular beans
						// (before 4.3 in particular when we didn't even look for collection beans).
						return null;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
				// We have exactly one match.
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			if (instanceCandidate instanceof Class) {
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			if (result instanceof NullBean) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignableValue(type, result)) {
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

findAutowireCandidates() 會調(diào)用 BeanFactoryUtils.beanNamesForTypeIncludingAncestors

底層通過類似雙親委派模型,找出所有的bean文章來源地址http://www.zghlxwxcb.cn/news/detail-579069.html

	public static String[] beanNamesForTypeIncludingAncestors(
			ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {

		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
		if (lbf instanceof HierarchicalBeanFactory) {
			HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
				String[] parentResult = beanNamesForTypeIncludingAncestors(
						(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
				result = mergeNamesWithParent(result, parentResult, hbf);
			}
		}
		return result;
	}

到了這里,關(guān)于Spring @Autowired 注解原理的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 為什么Spring和IDEA不推薦使用@Autowired注解,有哪些替代方案?

    為什么Spring和IDEA不推薦使用@Autowired注解,有哪些替代方案?

    在使用Spring框架和JetBrains IDEA集成開發(fā)環(huán)境(IDE)進行Java開發(fā)時,你可能經(jīng)常會遇到@Autowired注解。@Autowired是Spring框架中用于實現(xiàn)依賴注入的核心注解之一。然而,近年來,Spring和IDEA都不再推薦使用@Autowired注解,并提出了更好的替代方案。本文將詳細分析為什么Spring和IDEA不

    2024年02月07日
    瀏覽(23)
  • Spring和IDEA都不推薦用的@Autowired注解,為什么還有那么多人用?

    Spring和IDEA都不推薦用的@Autowired注解,為什么還有那么多人用?

    @Autowired的默認裝配 我們都知道在spring中@Autowired注解,是用來自動裝配對象的。通常,我們在項目中是這樣用的: 沒錯,這樣是能夠裝配成功的,因為默認情況下spring是按照類型裝配的,也就是我們所說的byType方式。 此外,@Autowired注解的required參數(shù)默認是true,表示開啟自動

    2023年04月18日
    瀏覽(24)
  • spring啟動流程 (5) Autowired原理

    BeanClass可以在構(gòu)造方法上標注@Autowired注解,Spring在創(chuàng)建Bean實例時將自動為其注入依賴參數(shù) Spring會優(yōu)先使用標注@Autowired注解的構(gòu)造方法 當一個構(gòu)造方法標注了@Autowired注解且required=true時,其余構(gòu)造方法不允許再標注@Autowired注解 當多個構(gòu)造方法標注了@Autowired注解且required=fa

    2024年02月16日
    瀏覽(19)
  • @Autowired和@Resource注解之間的關(guān)系區(qū)別,Bean的作用域和生命周期,Spring的執(zhí)行流程

    @Autowired和@Resource注解之間的關(guān)系區(qū)別,Bean的作用域和生命周期,Spring的執(zhí)行流程

    目錄 一. @Autowired 和 @Resource 注解 二. Bean的作用域? 1.?singleton(單例模式) 2.?prototype(原型模式)(多例模式) 3. 請求作用域:request 4. 會話作用域:session 三. Spring 的執(zhí)行流程 四. Bean 的生命周期? ?1. 實例化 ?2. 設(shè)置屬性? 3. Bean 初始化?? ? ?3.1 執(zhí)行各種各種 Aware 通知;? ? ?

    2024年02月04日
    瀏覽(24)
  • Spring源碼學習-后置處理器,Autowired實現(xiàn)原理

    Spring源碼學習-后置處理器,Autowired實現(xiàn)原理

    Autowired實現(xiàn)原理 populateBean 給創(chuàng)建好的bean實例進行普通屬性的賦值 InstantiationAwareBeanPostProcessor AutowiredAnnotationBeanPostProcessor 這個就是用來完成Autowired注解能夠自動裝配的bean后置處理器 這個方法初始化了一個set,用來存放需要解析的自動裝配注解,里面就包括Autowired,Value和Inject等

    2024年02月16日
    瀏覽(54)
  • 【注解使用】使用@Autowired后提示:Field injection is not recommended(Spring團隊不推薦使用Field注入)

    【注解使用】使用@Autowired后提示:Field injection is not recommended(Spring團隊不推薦使用Field注入)

    在使用 IDEA 開發(fā) SpringBoot 項目時,在? Controller ?類中使用注解? @Autowired ?注入一個依賴出現(xiàn)了警告提示,查看其他使用該注解的地方同樣出現(xiàn)了警告提示。這是怎么回事?由于先去使用了SpringBoot并沒有對Spring進行系統(tǒng)性學習,所以做一個記錄。 Field injection is not recommended(

    2024年02月12日
    瀏覽(19)
  • Spring CORS 跨域使用與原理(@CrossOrigin注解,Java配置類方式,xml方式)

    出于安全原因,瀏覽器禁止AJAX調(diào)用當前源之外的資源。 跨域資源共享(CORS)是由大多數(shù)瀏覽器實現(xiàn)的W3C規(guī)范,它允許您以一種靈活的方式指定授權(quán)哪種跨域請求,而不是使用一些不太安全、功能不太強大的hack(如IFrame或JSONP)。 Spring Framework 4.2 GA為CORS提供了一流的開箱即用支持

    2024年02月08日
    瀏覽(24)
  • Spring Boot 學習之——@SpringBootApplication注解(自動注解原理)

    Spring Boot 學習之——@SpringBootApplication注解(自動注解原理)

    springboot是基于spring的新型的輕量級框架,最厲害的地方當屬**自動配置。**那我們就可以根據(jù)啟動流程和相關(guān)原理來看看,如何實現(xiàn)傳奇的自動配置 從上面代碼可以看出,Annotation定義(@SpringBootApplication)和類定義(SpringApplication.run)最為耀眼,所以要揭開SpringBoot的神秘面紗

    2024年01月25日
    瀏覽(30)
  • Spring Boot 中@EnableAutoConfiguration注解原理

    Spring Boot 中@EnableAutoConfiguration注解原理

    開啟? Spring ?的自動裝配功能; 簡單點說就是Spring Boot根據(jù)依賴中的jar包,自動選擇 實例化 某些配置,配置類必須有@Configuration注解。 二、@EnableAutoConfiguration的原理 1.點進啟動類上的EnableAutoConfiguration注解 2.發(fā)現(xiàn)@EnableAutoConfiguration注解實際上也是@Import注解實現(xiàn)的(其實@Ena

    2024年01月17日
    瀏覽(31)
  • Spring cloud負載均衡 @LoadBalanced注解原理

    Spring cloud負載均衡 @LoadBalanced注解原理

    接上一篇文章,案例代碼也在上一篇文章的基礎(chǔ)上。 在上一篇文章的案例中,我們創(chuàng)建了作為Eureka server的Eureka注冊中心服務(wù)、作為Eureka client的userservice、orderservice。 orderservice引入RestTemplate,加入了@LoadBalanced注解,代碼如下: 從而,我們實現(xiàn)了基于Eureka注冊中心的微服務(wù)治

    2024年02月05日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包