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

spring自動裝配原理

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

為了搞明白自動裝配原理,需要知道spring容器管理bean的生命周期

Spring Bean 生命周期流程圖

spring自動裝配原理

bean自身方法的生命周期

分為四步:

//執(zhí)行此段代碼,spring容器的bean執(zhí)行實例化、屬性賦值、初始化
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    
//關閉容器,執(zhí)行銷毀
classPathXmlApplicationContext.close();

1、實例化

  • 讀取spring配置文件
  • 通過反射進行bean的實例化(eg:通過BeanFactory實例化)

2、屬性賦值

  • 解析自動裝配(byName、byType、constractor、default)DI的體現(xiàn)
  • 循環(huán)依賴

3、初始化

  • 調用XXXAware回調方法
  • 調用初始化生命周期回調(三種)
  • 如果bean實現(xiàn)aop創(chuàng)建動態(tài)代理

4、銷毀

  • 在spring容器關閉的時候進行調用
  • 調用初始化生命周期回調

對應上述文字,下圖展示了bean裝載到spring應用上下文種的一個典型的生命周期過程

spring自動裝配原理

spring自動裝配原理

@Autowired注解的自動裝配過程

先說結論:

@Autowired是在Bean屬性賦值階段進行裝配,通過Bean的后置處理器進行解析

1、在創(chuàng)建一個spring上下文的時候在構造函數(shù)中注冊AutowiredAnnotationBeanPostProcessor

2、在Bean的創(chuàng)建過程中進行解析

? ? ? ? 1、在實例化后預解析(解析@Autowired標注的屬性、方法,比如:把屬性的類型、名稱、屬性所在的類...元數(shù)據(jù)緩存)

? ? ? ? 2、在屬性賦值階段真正的注入(拿到上一步緩存的元數(shù)據(jù)去ioc容器進行查找,并且返回注入)

????????????????a.首先根據(jù)解析的元數(shù)據(jù)拿到類型去容器種查找

? ? ? ? ? ? ? ? ? ? ? ? *如果查詢結果剛好為一個,就將該bean裝配給@Autowired指定的數(shù)據(jù);

????????????????????????*如果查詢的結果不止一個,那么@Autowired會根據(jù)名稱來查找

????????????????????????*如果上述查找結果為空,那么就會拋出異常。

大致流程圖如下:

spring自動裝配原理

?@Autowired字段注入源碼分析

/* ......源碼注解過多,只貼一部分有用的
 * <h3>Not supported in {@code BeanPostProcessor} or {@code BeanFactoryPostProcessor}</h3>
 * <p>Note that actual injection is performed through a
 * {@link org.springframework.beans.factory.config.BeanPostProcessor
 * BeanPostProcessor} which in turn means that you <em>cannot</em>
 * use {@code @Autowired} to inject references into
 * {@link org.springframework.beans.factory.config.BeanPostProcessor
 * BeanPostProcessor} or
 * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessor}
 * types. Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
 * class (which, by default, checks for the presence of this annotation).
 *
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @author Sam Brannen
 * @since 2.5
 * @see AutowiredAnnotationBeanPostProcessor
 * @see Qualifier
 * @see Value
 */
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

	/**
	 * Declares whether the annotated dependency is required.
	 * <p>Defaults to {@code true}.
	 */
	boolean required() default true;

}

1、重點在注釋里的一句:

 Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}

2、AutowiredAnnotationBeanPostProcessor是Spring的后置處理器,專門處理@Autowired和@Value注解。查看AutowiredAnnotationBeanPostProcessor類,關注postProcessMergedBeanDefinition()方法、postProcessPropertyValues()方法和構造器;

//Spring在每個Bean實例化的時候,調用populateBean進行屬性注入的時候,即調用postProcessPropertyValues方法。
@Deprecated
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
	return postProcessProperties(pvs, bean, beanName);
}


//?Spring容器在每個Bean實例化之后,調用AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法。
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
	metadata.checkConfigMembers(beanDefinition);
}

//AutowiredAnnotationBeanPostProcessor構造器
public AutowiredAnnotationBeanPostProcessor() {
	//后置處理器將處理@Autowire注解
	this.autowiredAnnotationTypes.add(Autowired.class);
	//后置處理器將處理@Value注解
	this.autowiredAnnotationTypes.add(Value.class);
	try {
		//后置處理器將處理javax.inject.Inject JSR-330注解
		this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
				ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
		logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
	}
	catch (ClassNotFoundException ex) {
		// JSR-330 API not available - simply skip.
	}
}

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    //獲取指定類中autowire相關注解的元信息
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
	try {
        //對Bean的屬性進行自動注入
		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;
}

3、查看對Bean的屬性進行自動注入metadata.inject(bean, beanName, pvs);方法

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) {
			element.inject(target, beanName, pvs);
		}
	}
}

4、查看element.inject(target, beanName, pvs);方法

protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)throws Throwable {
	if (this.isField) {
		Field field = (Field) this.member;
		ReflectionUtils.makeAccessible(field);
		field.set(target, getResourceToInject(target, requestingBeanName));
	}
	else {
		if (checkPropertySkipping(pvs)) {
			return;
		}
		try {
			Method method = (Method) this.member;
			ReflectionUtils.makeAccessible(method);
			method.invoke(target, getResourceToInject(target, requestingBeanName));
		}
		catch (InvocationTargetException ex) {
			throw ex.getTargetException();
		}
	}
}

這是element.inject(target, beanName, pvs);的原始方法,它還有兩個子類自己實現(xiàn)的方法,如圖:

spring自動裝配原理

?此案例是字段注入分析,查看AutowiredFieldElement

//AutowiredAnnotationBeanPostProcessor.java

	@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
			value = resolvedCachedArgument(beanName, this.cachedFieldValue);
		}
		//沒有緩存
		else {
			//創(chuàng)建一個字段依賴描述符
			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);
			}
			//線程同步,確保容器中數(shù)據(jù)一致性
			synchronized (this) {
				//如果字段的值沒有緩存
				if (!this.cached) {
					//字段值不為null,并且required屬性為true
					if (value != null || this.required) {
						this.cachedFieldValue = desc;
						//為指定Bean注冊依賴Bean
						registerDependentBeans(beanName, autowiredBeanNames);
						if (autowiredBeanNames.size() == 1) {
							String autowiredBeanName = autowiredBeanNames.iterator().next();
							//如果容器中有指定名稱的Bean對象
							if (beanFactory.containsBean(autowiredBeanName)) {
								//依賴對象類型和字段類型匹配,默認按類型注入
								if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
									//創(chuàng)建一個依賴對象的引用,同時緩存
									this.cachedFieldValue = new ShortcutDependencyDescriptor(
											desc, autowiredBeanName, field.getType());
								}
							}
						}
					}
					//如果獲取的依賴關系為null,且獲取required屬性為false
					else {
						//將字段值的緩存設置為null
						this.cachedFieldValue = null;
					}
					//容器已經對當前字段的值緩存
					this.cached = true;
				}
			}
		}
		//如果字段值不為null
		if (value != null) {
			//顯式使用JDK的反射機制,設置自動的訪問控制權限為允許訪問
			ReflectionUtils.makeAccessible(field);
			//為字段賦值
			field.set(bean, value);
		}
	}

從注解@Value/@Autowired中獲取要注入的值,之后利用反射set到字段中。 重點就是怎么從注解中獲取要注入的值,我們來看核心代碼

value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
//DefaultListableBeanFactory.java

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

	descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
	if (Optional.class == descriptor.getDependencyType()) {
		return createOptionalDependency(descriptor, requestingBeanName);
	}
	else if (ObjectFactory.class == descriptor.getDependencyType() ||
			ObjectProvider.class == descriptor.getDependencyType()) {
		return new DependencyObjectProvider(descriptor, requestingBeanName);
	}
	else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
		return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
	}
	else {
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
				descriptor, requestingBeanName);
		if (result == null) {
			//真正獲取值的代碼
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		return result;
	}
	}

進行跟蹤:

//DefaultListableBeanFactory.java

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();

		//拿到@Value里的值
		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());
			return (descriptor.getField() != null ?
					converter.convertIfNecessary(value, type, descriptor.getField()) :
					converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
		}

		//如果標識@Autowired注解的屬性是集合類型,Array,Collection,Map,
		// 從這個方法獲取@Autowired里的值
<1>		Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
		if (multipleBeans != null) {
			return multipleBeans;
		}

		//如果標識@Autowired注解的屬性是非集合類型,
		// 從這個方法獲取@Autowired里的值
<2>		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		//如果沒有符合該類型的Bean
		if (matchingBeans.isEmpty()) {
			//是否是必須的
			if (isRequired(descriptor)) {
				//拋出異常
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			return null;
		}

		String autowiredBeanName;
		Object instanceCandidate;

		//如果符合該類型的Bean有多個
		if (matchingBeans.size() > 1) {
			//挑選出最優(yōu)解
<3>			autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
			if (autowiredBeanName == null) {
				if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
					//拋出異常
					return descriptor.resolveNotUnique(type, 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);
	}
	}

大致流程就是: 根據(jù)字段類型從IOC容器中獲取符合的Bean,如果有多個,則挑選出最優(yōu)的那一個。

<1>處:@Autowired注入集合數(shù)組,如Map.List。

<2>處:@Autowired注入非集合數(shù)組,即普通的類如Service

<3>處:多個同類型的bean中挑選出最優(yōu)解

總結:

????????在容器啟動,為bean屬性賦值的時候,spring會用后置處理器AutowiredAnnotationBeanPostProcessor解析@Autowired注解,來創(chuàng)建屬性的實例,然后從IOC容器中根據(jù)@Primary、@Order、@PriorityOrder或Spring默認規(guī)則挑選出最符合的Bean,利用反射注入到字段中完成賦值;文章來源地址http://www.zghlxwxcb.cn/news/detail-430772.html

到了這里,關于spring自動裝配原理的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

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

領支付寶紅包贊助服務器費用

相關文章

  • Spring Boot源碼解析 - 自動裝配原理

    Spring Boot源碼解析 - 自動裝配原理

    Spring Boot 自動裝配是 Spring Boot 框架的一個關鍵特性,它的目標是讓開發(fā)者能夠快速構建 Spring 應用程序,減少繁瑣的配置工作。 ? @SpringApplication 從啟動類 @SpringApplication 注解入手, @SpringBootApplication 是一個組合注解,它是 Spring Boot 框架中常用的一個主要注解之一。它結合了

    2024年01月19日
    瀏覽(36)
  • Spring Boot中自動裝配機制的原理

    Spring Boot中自動裝配機制的原理

    1 .自動裝配,簡單來說就是自動把第三方組件的Bean裝載到Spring IOC容器里面 ,不需要開發(fā)人員再去寫B(tài)ean的裝配配置, 2.在Spring Boot應用里面,只需要在啟動類加上 @SpringBootApplication 注解就可以實現(xiàn)自動裝配。 3.@SpringBootApplication是一個復合注解, 真正實現(xiàn)自動裝配的注解是@

    2024年02月10日
    瀏覽(23)
  • 【Spring Boot自動裝配原理詳解與常見面試題】—— 每天一點小知識

    【Spring Boot自動裝配原理詳解與常見面試題】—— 每天一點小知識

    ????????????????????????????????????????????????????????????? ?? S p r i n g B o o t 自動裝配原理詳解與常見面試題 color{#FF1493}{Spring Boot自動裝配原理詳解與常見面試題} Sp r in g B oo t 自動裝配原理詳解與常見面試題 ?? ????????? ?? 仰望天空

    2024年02月16日
    瀏覽(21)
  • spring boot自動裝配及自動裝配條件判斷

    spring boot自動裝配及自動裝配條件判斷

    第一步需要在pom.xml文件指定需要導入的坐標 要是沒有自動提示需要檢查maven有沒有 實現(xiàn)代碼 執(zhí)行代碼示例

    2024年02月20日
    瀏覽(24)
  • Spring Boot自動裝配

    Spring Boot自動裝配

    自動裝配是 Spring Boot 最核心的功能之一,第三方可以基于這個特性非常方便的和 Spring 做整合,實現(xiàn)自己的 Starter,做到開箱即用。 Java 早期并不支持注解,所以那會兒 Spring 只能通過 xml 的形式來配置。早期項目里要引入一個功能模塊,首先我們要引入 SDK,然后在 xml 里配置

    2024年01月23日
    瀏覽(37)
  • SpringBoot自動裝配原理

    ????????自動裝配簡單來說就是自動去把第三方的組件bean加載到springIOC容器當中,不需要開發(fā)人員再去寫bean相關的配置,springboot應用里面只需要把@SpringbootApplication注解加在啟動類上邊,就可完成自動配置的功能,而@SpringbootApplication是一個復合注解,真正完成自動配置功

    2024年01月22日
    瀏覽(25)
  • springboot自動裝配大概原理

    自動裝配 : pom.xml spring-boot-dependence:核心都依賴在父類工程中! 我們在寫入或者引入springboot依賴的時候,不需要指定版,因為有這些倉庫的版本 啟動器:------spring boot的啟動場景 比如spring-boot-starter-web,他就會幫我們導入web環(huán)境蘇需要的依賴。 springboot會將所有的功能場景

    2023年04月25日
    瀏覽(24)
  • SpringBoot自動裝配原理及分析

    SpringBoot自動裝配原理及分析

    在使用SpringBoot的時候,會自動將Bean裝配到IOC容器中。例如我們在使用Redis數(shù)據(jù)庫的時候,會引入依賴spring-boot-starter-data-redis。在引入這個依賴后,服務初始化的時候,會將操作Redis需要的組件注入到Ioc容器中進行后續(xù)使用。 自動裝配的大致過程如下: 獲取到組件(spring-boo

    2024年01月21日
    瀏覽(18)
  • 深入了解Spring Boot自動裝配

    Spring Boot的自動裝配是一項強大的功能,能夠簡化應用程序的配置和開發(fā)過程。讓我們通過一系列詳細的例子來深入了解這一特性。 在Spring Boot中,自動裝配是指框架根據(jù)應用程序的依賴關系,自動配置和裝配相應的Bean,而無需手動設置。這使得開發(fā)者可以更專注于業(yè)務邏輯

    2024年01月23日
    瀏覽(30)
  • spring中的Bean的自動裝配

    自動裝配是使用spring滿足bean依賴的一種方法 spring會在應用上下文中為某個bean尋找其依賴的bean 在xml中顯式配置;(bean標簽和property標簽) 在java中顯式配置;(get,set方法) 隱式的bean發(fā)現(xiàn)機制和自動裝配。(自動裝配) Spring的自動裝配需要從兩個角度來實現(xiàn),或者說是兩個

    2024年02月15日
    瀏覽(18)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領取紅包

二維碼2

領紅包