最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring中@Configuration注解修改的類生成代理原因解析

 更新時(shí)間:2022年02月08日 11:34:36   作者:碼拉松  
大家好,本篇文章主要講的是Spring中@Configuration注解修改的類生成代理原因解析,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下

前言

在Spring中只要被@Configuration注解修飾的類,Spring就會(huì)為其生成代理對(duì)象,至于這樣做的主要原因就是為了解決生成對(duì)象的單例問(wèn)題。

說(shuō)明

實(shí)際上作者在ConfigurationClassEnhancer這個(gè)類也有注解說(shuō)明

在這里插入圖片描述

場(chǎng)景

如果Spring不做處理,下面輸出的一定的是false,但是實(shí)際上輸出的結(jié)果是true,那么只有可能是代理類做了特殊處理。

@Configuration
public class MyConfiguration {
    @Bean
    public TestA a(){
        return new TestA();
    }
    @Bean
    public TestB b(){
        TestA a = a();
        TestA b = a();
        System.out.println(a == b);
        return new TestB();
    }
}

處理分析

生成的代理對(duì)象,最終會(huì)調(diào)用ConfigurationClassEnhancer內(nèi)部類BeanMethodInterceptor的intercept方法,如果不是當(dāng)前調(diào)用的Bean對(duì)象(也就是isCurrentlyInvokedFactoryMethod(beanMethod)返回false),則會(huì)調(diào)用resolveBeanReference方法。

public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
			MethodProxy cglibMethodProxy) throws Throwable {
	ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
	String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
	// Determine whether this bean is a scoped-proxy
	if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
		String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
		if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
			beanName = scopedBeanName;
		}
	}
	// To handle the case of an inter-bean method reference, we must explicitly check the
	// container for already cached instances.
	// First, check to see if the requested bean is a FactoryBean. If so, create a subclass
	// proxy that intercepts calls to getObject() and returns any cached bean instance.
	// This ensures that the semantics of calling a FactoryBean from within @Bean methods
	// is the same as that of referring to a FactoryBean within XML. See SPR-6602.
	if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
			factoryContainsBean(beanFactory, beanName)) {
		Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
		if (factoryBean instanceof ScopedProxyFactoryBean) {
			// Scoped proxy factory beans are a special case and should not be further proxied
		}
		else {
			// It is a candidate FactoryBean - go ahead with enhancement
			return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
		}
	}
	if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
		// The factory is calling the bean method in order to instantiate and register the bean
		// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
		// create the bean instance.
		if (logger.isInfoEnabled() &&
				BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
			logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
							"assignable to Spring's BeanFactoryPostProcessor interface. This will " +
							"result in a failure to process annotations such as @Autowired, " +
							"@Resource and @PostConstruct within the method's declaring " +
							"@Configuration class. Add the 'static' modifier to this method to avoid " +
							"these container lifecycle issues; see @Bean javadoc for complete details.",
					beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
		}
		return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
	}
	return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}

此方法會(huì)通過(guò)getBean來(lái)獲取對(duì)象,這樣就可以控制對(duì)象的生成了。

private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
		ConfigurableBeanFactory beanFactory, String beanName) {
	// The user (i.e. not the factory) is requesting this bean through a call to
	// the bean method, direct or indirect. The bean may have already been marked
	// as 'in creation' in certain autowiring scenarios; if so, temporarily set
	// the in-creation status to false in order to avoid an exception.
	boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
	try {
		if (alreadyInCreation) {
			beanFactory.setCurrentlyInCreation(beanName, false);
		}
		boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
		if (useArgs && beanFactory.isSingleton(beanName)) {
			// Stubbed null arguments just for reference purposes,
			// expecting them to be autowired for regular singleton references?
			// A safe assumption since @Bean singleton arguments cannot be optional...
			for (Object arg : beanMethodArgs) {
				if (arg == null) {
					useArgs = false;
					break;
				}
			}
		}
		// 通過(guò)getBean就可以控制對(duì)象的生成,對(duì)象如果生成過(guò),則可以直接從一級(jí)緩存中獲取
		Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
				beanFactory.getBean(beanName));
		if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
			// Detect package-protected NullBean instance through equals(null) check
			if (beanInstance.equals(null)) {
				if (logger.isDebugEnabled()) {
					logger.debug(String.format("@Bean method %s.%s called as bean reference " +
							"for type [%s] returned null bean; resolving to null value.",
							beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
							beanMethod.getReturnType().getName()));
				}
				beanInstance = null;
			}
			else {
				String msg = String.format("@Bean method %s.%s called as bean reference " +
						"for type [%s] but overridden by non-compatible bean instance of type [%s].",
						beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
						beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
				try {
					BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
					msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
				}
				catch (NoSuchBeanDefinitionException ex) {
					// Ignore - simply no detailed message then.
				}
				throw new IllegalStateException(msg);
			}
		}
		Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
		if (currentlyInvoked != null) {
			String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
			beanFactory.registerDependentBean(beanName, outerBeanName);
		}
		return beanInstance;
	}
	finally {
		if (alreadyInCreation) {
			beanFactory.setCurrentlyInCreation(beanName, true);
		}
	}
}

總結(jié)

到此這篇關(guān)于Spring中@Configuration注解修改的類生成代理原因解析的文章就介紹到這了,更多相關(guān)Spring @Configuration注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中守護(hù)線程介紹及使用

    Java中守護(hù)線程介紹及使用

    大家好,本篇文章主要講的是Java中守護(hù)線程介紹及使用,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01
  • springmvc前臺(tái)向后臺(tái)傳值幾種方式總結(jié)(從簡(jiǎn)單到復(fù)雜)

    springmvc前臺(tái)向后臺(tái)傳值幾種方式總結(jié)(從簡(jiǎn)單到復(fù)雜)

    今天小編就為大家分享一篇springmvc前臺(tái)向后臺(tái)傳值幾種方式總結(jié)(從簡(jiǎn)單到復(fù)雜),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Java中字符序列的替換與分解的幾種實(shí)現(xiàn)方法

    Java中字符序列的替換與分解的幾種實(shí)現(xiàn)方法

    本文主要介紹了Java中字符序列的替換與分解的幾種實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • IDEA報(bào)錯(cuò):java?找不到符號(hào)圖文解決過(guò)程

    IDEA報(bào)錯(cuò):java?找不到符號(hào)圖文解決過(guò)程

    這篇文章主要給大家介紹了關(guān)于IDEA報(bào)錯(cuò):java?找不到符號(hào)解決的相關(guān)資料,運(yùn)行項(xiàng)目時(shí)Idea報(bào)錯(cuò),提示找不到符號(hào),但是這個(gè)類在項(xiàng)目里是存在的,網(wǎng)上找了很多文章都沒(méi)解決,浪費(fèi)了一個(gè)下午終于弄好了,記錄一下,需要的朋友可以參考下
    2023-08-08
  • mybatis-plus使用問(wèn)題小結(jié)

    mybatis-plus使用問(wèn)題小結(jié)

    這篇文章主要介紹了mybatis-plus使用問(wèn)題匯總,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • ElasticSearch整合SpringBoot搭建配置

    ElasticSearch整合SpringBoot搭建配置

    這篇文章主要為大家介紹了ElasticSearch整合SpringBoot搭建配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • javaweb實(shí)現(xiàn)在線支付功能

    javaweb實(shí)現(xiàn)在線支付功能

    這篇文章主要為大家詳細(xì)介紹了javaweb實(shí)現(xiàn)在線支付功能的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 如何使用BufferedReader循環(huán)讀文件

    如何使用BufferedReader循環(huán)讀文件

    這篇文章主要介紹了如何使用BufferedReader循環(huán)讀文件的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 使用IDEA打jar包的詳細(xì)圖文教程

    使用IDEA打jar包的詳細(xì)圖文教程

    JAR文件是一種壓縮文件,與常見(jiàn)的ZIP壓縮文件兼容,被稱為JAR包,下面這篇文章主要給大家介紹了關(guān)于使用IDEA打jar包的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • 使用spring框架中的組件發(fā)送郵件功能說(shuō)明

    使用spring框架中的組件發(fā)送郵件功能說(shuō)明

    Spring使用的是基本的JavaBean來(lái)完成以前只可能由EJB完成的事情。這篇文章主要介紹了使用spring框架中的組件發(fā)送郵件,需要的朋友可以參考下
    2017-11-11

最新評(píng)論

松江区| 安康市| 十堰市| 新田县| 同德县| 拉孜县| 承德市| 都安| 福安市| 分宜县| 桦南县| 新闻| 城口县| 东明县| 来凤县| 错那县| 衡南县| 牡丹江市| 台东县| 阿克陶县| 林口县| 旬邑县| 丰顺县| 湖南省| 清河县| 衡阳县| 敦煌市| 岳池县| 巴彦县| 商城县| 嘉荫县| 衡山县| 新津县| 吐鲁番市| 大同县| 怀集县| 海盐县| 鄂州市| 敦化市| 卓尼县| 建湖县|