欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot中將@Bean方法解析為BeanDefinition詳解

 更新時間:2023年12月05日 10:32:29   作者:流煙默  
這篇文章主要介紹了SpringBoot中將@Bean方法解析為BeanDefinition詳解,得到的BeanDefinition是ConfigurationClassBeanDefinition類型,會為BeanDefinition設(shè)置factoryMethodName,這意味著當(dāng)實例化這個bean的時候?qū)⒉捎霉S方法,需要的朋友可以參考下

SpringBoot如何將@Bean方法注冊為BeanDefinition

我們以MybatisPlusAutoConfiguration為例說明sqlSessionFactory()這個方法如何解析為BeanDefinition。

@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
//...
}    

這個解析過程是在ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsForBeanMethod方法。

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
	ConfigurationClass configClass = beanMethod.getConfigurationClass();
	MethodMetadata metadata = beanMethod.getMetadata();
	//本文這里是sqlSessionFactory
	String methodName = metadata.getMethodName();
	// Do we need to mark the bean as skipped by its condition?
	//判斷是否需要跳過
	if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
		configClass.skippedBeanMethods.add(methodName);
		return;
	}
		//判斷是否需要跳過
	if (configClass.skippedBeanMethods.contains(methodName)) {
		return;
	}
//獲取到@Bean的注解信息
	AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
	Assert.state(bean != null, "No @Bean annotation attributes");
	// Consider name and any aliases
	List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
	//嘗試獲取bean的名稱,默認使用methodName
	String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
	// Register aliases even when overridden
	//嘗試注冊別名
	for (String alias : names) {
		this.registry.registerAlias(beanName, alias);
	}
	// Has this effectively been overridden before (e.g. via XML)?
	//校驗BeanDefinition是否存在、是否允許覆蓋
	if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
		if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
			throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
					beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
					"' clashes with bean name for containing configuration class; please make those names unique!");
		}
		return;
	}
//得到一個ConfigurationClassBeanDefinition 
	ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
	beanDef.setResource(configClass.getResource());
	beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
//方法是否為靜態(tài)方法
	if (metadata.isStatic()) {
		// static @Bean method
		if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
			beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
		}
		else {
			beanDef.setBeanClassName(configClass.getMetadata().getClassName());
		}
		beanDef.setUniqueFactoryMethodName(methodName);
	}
	else {
	//實例方法,非靜態(tài)方法
		// instance @Bean method
		//設(shè)置FactoryBeanName,本文這里是
		//com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration
		beanDef.setFactoryBeanName(configClass.getBeanName());
		// 設(shè)置factoryMethodName 本文這里是sqlSessionFactory
		beanDef.setUniqueFactoryMethodName(methodName);
	}
//本文這里跳過 這里是SimpleMethodMetadata
	if (metadata instanceof StandardMethodMetadata) {
		beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
	}
//設(shè)置注入標(biāo)識  AUTOWIRE_CONSTRUCTOR=3
	beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
	//設(shè)置SKIP_REQUIRED_CHECK_ATTRIBUTE屬性
	beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
			SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
//BeanDefinition的通用后置處理,如Lazy、Primary、DependsOn、Role以及Description
	AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
//解析注解上配置的autowire
	Autowire autowire = bean.getEnum("autowire");
	if (autowire.isAutowire()) {
		beanDef.setAutowireMode(autowire.value());
	}
//解析注解上配置的autowireCandidate
	boolean autowireCandidate = bean.getBoolean("autowireCandidate");
	if (!autowireCandidate) {
		beanDef.setAutowireCandidate(false);
	}
//解析注解上配置的initMethod
	String initMethodName = bean.getString("initMethod");
	if (StringUtils.hasText(initMethodName)) {
		beanDef.setInitMethodName(initMethodName);
	}
//解析注解上配置的destroyMethod
	String destroyMethodName = bean.getString("destroyMethod");
	beanDef.setDestroyMethodName(destroyMethodName);
	// Consider scoping
	ScopedProxyMode proxyMode = ScopedProxyMode.NO;
	//獲取@Scope注解信息
	AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
	if (attributes != null) {
		beanDef.setScope(attributes.getString("value"));
		proxyMode = attributes.getEnum("proxyMode");
		if (proxyMode == ScopedProxyMode.DEFAULT) {
			proxyMode = ScopedProxyMode.NO;
		}
	}
	// Replace the original bean definition with the target one, if necessary
	BeanDefinition beanDefToRegister = beanDef;
	if (proxyMode != ScopedProxyMode.NO) {
	//嘗試創(chuàng)建代理
		BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
				new BeanDefinitionHolder(beanDef, beanName), this.registry,
				proxyMode == ScopedProxyMode.TARGET_CLASS);
		beanDefToRegister = new ConfigurationClassBeanDefinition(
				(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
	}
	if (logger.isTraceEnabled()) {
		logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
				configClass.getMetadata().getClassName(), beanName));
	}
	//注冊BeanDefinition,beanName默認是methodName sqlSessionFactory
	this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}

方法流程如上所示,核心步驟都加了注釋。這里要特別注意的是如下幾點:

  • 得到的BeanDefinition是ConfigurationClassBeanDefinition類型;
  • 會為BeanDefinition設(shè)置factoryMethodName,這意味著當(dāng)實例化這個bean的時候?qū)⒉捎霉S方法;
  • 會區(qū)分方法是否為靜態(tài)方法來設(shè)置BeanClass或者FactoryBeanName

這里得到的configClass

在這里插入圖片描述

這里得到的MethodMetadata

在這里插入圖片描述

最終得到的BeanDefinition屬性

annotationMetadata = {SimpleAnnotationMetadata@5352} 
factoryMethodMetadata = {SimpleMethodMetadata@5635} 
decoratedDefinition = null
qualifiedElement = null
stale = false
allowCaching = true
isFactoryMethodUnique = true
targetType = null
resolvedTargetType = null
isFactoryBean = null
factoryMethodReturnType = null
factoryMethodToIntrospect = null
constructorArgumentLock = {Object@5823} 
resolvedConstructorOrFactoryMethod = null
constructorArgumentsResolved = false
resolvedConstructorArguments = null
preparedConstructorArguments = null
postProcessingLock = {Object@5824} 
postProcessed = false
beforeInstantiationResolved = null
externallyManagedConfigMembers = null
externallyManagedInitMethods = null
externallyManagedDestroyMethods = null
beanClass = null
scope = ""
abstractFlag = false
lazyInit = null
autowireMode = 3
dependencyCheck = 0
dependsOn = null
autowireCandidate = true
primary = false
qualifiers = {LinkedHashMap@5825}  size = 0
instanceSupplier = null
nonPublicAccessAllowed = true
lenientConstructorResolution = false
factoryBeanName = "com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration"
factoryMethodName = "sqlSessionFactory"
constructorArgumentValues = null
propertyValues = null
methodOverrides = {MethodOverrides@5826} 
initMethodName = null
destroyMethodName = "(inferred)"
enforceInitMethod = true
enforceDestroyMethod = true
synthetic = false
role = 0
description = null
resource = {ClassPathResource@5353} "class path resource [com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.class]"
source = {SimpleMethodMetadata@5635} 
attributes = {LinkedHashMap@5827}  size = 1

到此這篇關(guān)于SpringBoot中將@Bean方法解析為BeanDefinition詳解的文章就介紹到這了,更多相關(guān)@Bean方法解析為BeanDefinition內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Reactor如何優(yōu)雅Exception異常處理

    詳解Reactor如何優(yōu)雅Exception異常處理

    初識響應(yīng)式編程的時候,除了從命令式的思維方式轉(zhuǎn)變?yōu)楹瘮?shù)式的編程方式外,其中有一個很大的不適應(yīng)的地方就是在面對異常時該怎么處理。本文將通過Project?Reactor的文檔以及源碼來深入解讀,在reactor中是如何優(yōu)雅地實現(xiàn)這異常處理三板斧,希望對大家有所幫助
    2023-02-02
  • 詳解CopyOnWriteArrayList是如何保證線程安全

    詳解CopyOnWriteArrayList是如何保證線程安全

    這篇文章主要為大家介紹了CopyOnWriteArrayList是如何保證線程安全講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • 最簡單的Spring Cloud教程第一篇:服務(wù)的注冊與發(fā)現(xiàn)(Eureka)

    最簡單的Spring Cloud教程第一篇:服務(wù)的注冊與發(fā)現(xiàn)(Eureka)

    這篇文章主要給大家介紹了關(guān)于Spring Cloud服務(wù)的注冊與發(fā)現(xiàn)(Eureka)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用spring cloud具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。
    2017-08-08
  • 解決調(diào)試JDK源碼時,不能查看變量的值問題

    解決調(diào)試JDK源碼時,不能查看變量的值問題

    下面小編就為大家?guī)硪黄鉀Q調(diào)試JDK源碼時,不能查看變量的值問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • java中使用Files.readLines()處理文本中行數(shù)據(jù)方式

    java中使用Files.readLines()處理文本中行數(shù)據(jù)方式

    這篇文章主要介紹了java中使用Files.readLines()處理文本中行數(shù)據(jù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Spring Cloud Alibaba Nacos Config加載配置詳解流程

    Spring Cloud Alibaba Nacos Config加載配置詳解流

    這篇文章主要介紹了Spring Cloud Alibaba Nacos Config配置中心實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2022-07-07
  • 使用Spring Data Jpa的CriteriaQuery一個陷阱

    使用Spring Data Jpa的CriteriaQuery一個陷阱

    使用Spring Data Jpa的CriteriaQuery進行動態(tài)條件查詢時,可能會遇到一個陷阱,當(dāng)條件為空時,查詢不到任何結(jié)果,并不是期望的返回所有結(jié)果。這是為什么呢?
    2020-11-11
  • java實現(xiàn)字符串排列組合問題

    java實現(xiàn)字符串排列組合問題

    這篇文章主要為大家詳細介紹了java實現(xiàn)字符串排列組合問題,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • ArrayList及HashMap的擴容規(guī)則講解

    ArrayList及HashMap的擴容規(guī)則講解

    今天小編就為大家分享一篇關(guān)于ArrayList及HashMap的擴容規(guī)則講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • SpringSecurity OAtu2+JWT實現(xiàn)微服務(wù)版本的單點登錄的示例

    SpringSecurity OAtu2+JWT實現(xiàn)微服務(wù)版本的單點登錄的示例

    本文主要介紹了SpringSecurity OAtu2+JWT實現(xiàn)微服務(wù)版本的單點登錄的示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05

最新評論