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

Spring中的InitializingBean和SmartInitializingSingleton的區(qū)別詳解

 更新時(shí)間:2024年01月09日 10:44:48   作者:lkforce  
這篇文章主要介紹了Spring中的InitializingBean和SmartInitializingSingleton的區(qū)別詳解,InitializingBean只有一個(gè)接口方法afterPropertiesSet(),在BeanFactory初始化完這個(gè)bean,并且把bean的參數(shù)都注入成功后調(diào)用一次afterPropertiesSet()方法,需要的朋友可以參考下

一,InitializingBean簡(jiǎn)介

InitializingBean的代碼:

package org.springframework.beans.factory;
/**
 * Interface to be implemented by beans that need to react once all their
 * properties have been set by a BeanFactory: for example, to perform custom
 * initialization, or merely to check that all mandatory properties have been set.
 *
 * <p>An alternative to implementing InitializingBean is specifying a custom
 * init-method, for example in an XML bean definition.
 * For a list of all bean lifecycle methods, see the
 * {@link BeanFactory BeanFactory javadocs}.
 *
 * @author Rod Johnson
 * @see BeanNameAware
 * @see BeanFactoryAware
 * @see BeanFactory
 * @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName
 * @see org.springframework.context.ApplicationContextAware
 */
public interface InitializingBean {
	/**
	 * Invoked by a BeanFactory after it has set all bean properties supplied
	 * (and satisfied BeanFactoryAware and ApplicationContextAware).
	 * <p>This method allows the bean instance to perform initialization only
	 * possible when all bean properties have been set and to throw an
	 * exception in the event of misconfiguration.
	 * @throws Exception in the event of misconfiguration (such
	 * as failure to set an essential property) or if initialization fails.
	 */
	void afterPropertiesSet() throws Exception;
}

說明:

1,InitializingBean只有一個(gè)接口方法:afterPropertiesSet()

2,InitializingBean接口可以被bean實(shí)現(xiàn),并重寫afterPropertiesSet()方法。

3,功能:在BeanFactory初始化完這個(gè)bean,并且把bean的參數(shù)都注入成功后調(diào)用一次afterPropertiesSet()方法。

4,InitializingBean有個(gè)功能類似的替換方案:在XML配置文件中配置init-method。

二,SmartInitializingSingleton簡(jiǎn)介

SmartInitializingSingleton的代碼:

package org.springframework.beans.factory;
/**
 * Callback interface triggered at the end of the singleton pre-instantiation phase
 * during {@link BeanFactory} bootstrap. This interface can be implemented by
 * singleton beans in order to perform some initialization after the regular
 * singleton instantiation algorithm, avoiding side effects with accidental early
 * initialization (e.g. from {@link ListableBeanFactory#getBeansOfType} calls).
 * In that sense, it is an alternative to {@link InitializingBean} which gets
 * triggered right at the end of a bean's local construction phase.
 *
 * <p>This callback variant is somewhat similar to
 * {@link org.springframework.context.event.ContextRefreshedEvent} but doesn't
 * require an implementation of {@link org.springframework.context.ApplicationListener},
 * with no need to filter context references across a context hierarchy etc.
 * It also implies a more minimal dependency on just the {@code beans} package
 * and is being honored by standalone {@link ListableBeanFactory} implementations,
 * not just in an {@link org.springframework.context.ApplicationContext} environment.
 *
 * <p><b>NOTE:</b> If you intend to start/manage asynchronous tasks, preferably
 * implement {@link org.springframework.context.Lifecycle} instead which offers
 * a richer model for runtime management and allows for phased startup/shutdown.
 *
 * @author Juergen Hoeller
 * @since 4.1
 * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons()
 */
public interface SmartInitializingSingleton {
	/**
	 * Invoked right at the end of the singleton pre-instantiation phase,
	 * with a guarantee that all regular singleton beans have been created
	 * already. {@link ListableBeanFactory#getBeansOfType} calls within
	 * this method won't trigger accidental side effects during bootstrap.
	 * <p><b>NOTE:</b> This callback won't be triggered for singleton beans
	 * lazily initialized on demand after {@link BeanFactory} bootstrap,
	 * and not for any other bean scope either. Carefully use it for beans
	 * with the intended bootstrap semantics only.
	 */
	void afterSingletonsInstantiated();
}

說明:

1,SmartInitializingSingleton中只有一個(gè)接口方法:afterSingletonsInstantiated()

2,從注釋中可以看到,SmartInitializingSingleton接口可以被單例的bean實(shí)現(xiàn),并重寫afterSingletonsInstantiated()方法。

3,bean的afterSingletonsInstantiated()方法是在所有單例bean都初始化完成后才會(huì)調(diào)用的。

4,此接口可以解決一些因?yàn)閎ean初始化太早而出現(xiàn)的錯(cuò)誤和問題。

5,此接口是從Spring4.1版本開始使用的。

6,此接口可以作為InitializingBean接口的一種替代方案。

三,InitializingBean和SmartInitializingSingleton的區(qū)別

1,SmartInitializingSingleton只作用于單例bean,InitializingBean無此要求。但他們都不能用于懶加載的bean。

2,SmartInitializingSingleton是在所有單例Bean都初始化完成后調(diào)用的,InitializingBean是每個(gè)bean初始化完成后就會(huì)調(diào)用。

四,從源碼觀察InitializingBean和SmartInitializingSingleton調(diào)用時(shí)機(jī)的區(qū)別

在Spring進(jìn)行依賴注入的過程中,代碼會(huì)來到DefaultListableBeanFactory類的preInstantiateSingletons()方法:

@Override
public void preInstantiateSingletons() throws BeansException {
	if (this.logger.isDebugEnabled()) {
		this.logger.debug("Pre-instantiating singletons in " + this);
	}
	// Iterate over a copy to allow for init methods which in turn register new bean definitions.
	// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
	// Trigger initialization of all non-lazy singleton beans...
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
			if (isFactoryBean(beanName)) {
				Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
				if (bean instanceof FactoryBean) {
					final FactoryBean<?> factory = (FactoryBean<?>) bean;
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
										((SmartFactoryBean<?>) factory)::isEagerInit,
								getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					if (isEagerInit) {
						getBean(beanName);
					}
				}
			}
			else {
				getBean(beanName);
			}
		}
	}
	// Trigger post-initialization callback for all applicable beans...
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName);
		if (singletonInstance instanceof SmartInitializingSingleton) {
			final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					smartSingleton.afterSingletonsInstantiated();
					return null;
				}, getAccessControlContext());
			}
			else {
				smartSingleton.afterSingletonsInstantiated();
			}
		}
	}
}

方法很明確的分成了兩部分。

第一部分是從beanDefinitionNames列表中獲得所有要注入的bean,然后調(diào)用getBean()方法完成對(duì)bean的注入,InitializingBean. afterPropertiesSet()就是在getBean()方法中調(diào)用的。

第二部分再一次從beanDefinitionNames列表中獲得所有要注入的bean,并且調(diào)用他們的SmartInitializingSingleton. afterSingletonsInstantiated()方法。

以上就是這兩個(gè)接口生效位置的不同。

下面還可以看一下具體調(diào)用InitializingBean. afterPropertiesSet()方法的代碼,在上面第一部分調(diào)用getBean()方法的代碼中,經(jīng)過多層調(diào)用,代碼會(huì)來到AbstractAutowireCapableBeanFactory的invokeInitMethods()方法:

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
		throws Throwable {
	boolean isInitializingBean = (bean instanceof InitializingBean);
	if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
		if (logger.isDebugEnabled()) {
			logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
		}
		if (System.getSecurityManager() != null) {
			try {
				AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
					((InitializingBean) bean).afterPropertiesSet();
					return null;
				}, getAccessControlContext());
			}
			catch (PrivilegedActionException pae) {
				throw pae.getException();
			}
		}
		else {
			((InitializingBean) bean).afterPropertiesSet();
		}
	}
	if (mbd != null && bean.getClass() != NullBean.class) {
		String initMethodName = mbd.getInitMethodName();
		if (StringUtils.hasLength(initMethodName) &&
				!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
				!mbd.isExternallyManagedInitMethod(initMethodName)) {
			invokeCustomInitMethod(beanName, bean, mbd);
		}
	}
}

這個(gè)方法的代碼也是分成了明顯的兩部分,第一部分代碼就是調(diào)用bean的afterPropertiesSet()方法,第二部分調(diào)用了bean的initMethod,這個(gè)initMethod是可以在配置文件中配置的。

通過這個(gè)方法可以看到,afterPropertiesSet()方法是在initMethod之前調(diào)用的,而且看起來如果afterPropertiesSet()方法如果拋出了異常,那么initMethod方法也不會(huì)調(diào)用了(沒有安全管理器的話)。

到此這篇關(guān)于Spring中的InitializingBean和SmartInitializingSingleton的區(qū)別詳解的文章就介紹到這了,更多相關(guān)InitializingBean和SmartInitializingSingleton區(qū)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySql設(shè)置指定用戶數(shù)據(jù)庫查看查詢權(quán)限

    MySql設(shè)置指定用戶數(shù)據(jù)庫查看查詢權(quán)限

    這篇文章主要介紹了MySql設(shè)置指定用戶數(shù)據(jù)庫查看查詢權(quán)限,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • ubuntu?22.04安裝mysql?8.0步驟與避坑指南

    ubuntu?22.04安裝mysql?8.0步驟與避坑指南

    MySQL最流行的關(guān)系型數(shù)據(jù)庫管理系統(tǒng),在WEB應(yīng)用方面MySQL是最好的關(guān)系數(shù)據(jù)庫管理系統(tǒng)應(yīng)用軟件之一,這篇文章主要給大家介紹了關(guān)于ubuntu?22.04安裝mysql?8.0步驟與避坑指南的相關(guān)資料,需要的朋友可以參考下
    2023-12-12
  • MySQL如何設(shè)置動(dòng)態(tài)創(chuàng)建時(shí)間(create_time)和修改時(shí)間(update_time)

    MySQL如何設(shè)置動(dòng)態(tài)創(chuàng)建時(shí)間(create_time)和修改時(shí)間(update_time)

    本文主要介紹了MySQL如何設(shè)置動(dòng)態(tài)創(chuàng)建時(shí)間(create_time)和修改時(shí)間(update_time),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • mysql 正確清理binlog日志的兩種方法

    mysql 正確清理binlog日志的兩種方法

    這篇文章主要介紹了mysql 正確清理binlog日志的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • MySQL 隨機(jī)函數(shù)獲取數(shù)據(jù)速度和效率分析

    MySQL 隨機(jī)函數(shù)獲取數(shù)據(jù)速度和效率分析

    最近做項(xiàng)目,需要做一個(gè)從mysql數(shù)據(jù)庫中隨機(jī)取幾條數(shù)據(jù)出來。總所周知,order by rand 會(huì)死人的。。因?yàn)楸救藢?duì)大數(shù)據(jù)量方面的只是了解的很少,無解,去找百度老師。。搜索結(jié)果千篇一律。特發(fā)到這里來,供大家學(xué)習(xí),需要的朋友可以參考下
    2016-11-11
  • MySQL索引失效的典型案例

    MySQL索引失效的典型案例

    索引在我們使用MySQL數(shù)據(jù)庫時(shí)可以極大的提高查詢效率,然而,有時(shí)候因?yàn)槭褂蒙系囊恍╄Υ镁蜁?huì)導(dǎo)致索引的失效,無法達(dá)到我們使用索引的預(yù)期效果,今天介紹一種MySQL中幾種常見的索引失效的原因,可以在以后的工作中盡可能避免因索引失效帶來的坑。
    2021-06-06
  • MySQL數(shù)據(jù)庫命令

    MySQL數(shù)據(jù)庫命令

    這篇文章主要介紹了數(shù)據(jù)庫的常用命令,數(shù)據(jù)庫中對(duì)表的命令以及一些常用的數(shù)據(jù)庫查詢和常用函數(shù),感興趣的小伙伴可以借鑒一下
    2023-03-03
  • 如何使用mysql查詢24小時(shí)數(shù)據(jù)

    如何使用mysql查詢24小時(shí)數(shù)據(jù)

    在進(jìn)行實(shí)時(shí)數(shù)據(jù)處理時(shí),我們常常需要查詢最近24小時(shí)的數(shù)據(jù)來進(jìn)行分析和處理,下面我們將介紹如何使用MySQL查詢最近24小時(shí)的數(shù)據(jù),需要的朋友可以參考下
    2023-07-07
  • MySQL聯(lián)合索引遵循最左前綴匹配原則

    MySQL聯(lián)合索引遵循最左前綴匹配原則

    這篇文章主要介紹了MySQL聯(lián)合索引遵循最左前綴匹配原則,?MySQL聯(lián)合索引遵循最左前綴匹配原則,即最左優(yōu)先,查詢的時(shí)候會(huì)優(yōu)先匹配最左邊的索引
    2022-08-08
  • MySQL的復(fù)合查詢功能實(shí)現(xiàn)

    MySQL的復(fù)合查詢功能實(shí)現(xiàn)

    orners查詢AssistantAssistant*從真實(shí)的工程項(xiàng)目中,我們經(jīng)常需要使用多表進(jìn)行查詢,單表查詢實(shí)際上是開發(fā)中,數(shù)據(jù)來自多張表,因此需要進(jìn)行多表查詢,本文通過實(shí)例代碼介紹MySQL的復(fù)合查詢功能實(shí)現(xiàn),感興趣的朋友一起看看吧
    2026-05-05

最新評(píng)論

五大连池市| 邳州市| 武夷山市| 什邡市| 抚顺县| 曲水县| 盐亭县| 颍上县| 辉南县| 出国| 慈利县| 阳新县| 通山县| 南陵县| 张家口市| 蒲城县| 东辽县| 石河子市| 綦江县| 宿迁市| 右玉县| 东明县| 涞源县| 洪湖市| 凌云县| 广灵县| 姜堰市| 彝良县| 丰县| 惠安县| 福海县| 温宿县| 延津县| 丽江市| 连州市| 哈巴河县| 光泽县| 沛县| 河津市| 崇阳县| 泉州市|