亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

這一次搞懂Spring的Bean實例化原理操作

 更新時間:2020年08月26日 08:45:39   作者:夜勿語  
這篇文章主要介紹了這一次搞懂Spring的Bean實例化原理操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

前言

前兩篇文章分析了Spring XML和注解的解析原理,并將其封裝為BeanDefinition對象存放到IOC容器中,而這些只是refresh方法中的其中一個步驟——obtainFreshBeanFactory,接下來就將圍繞著這些BeanDefinition對象進(jìn)行一系列的處理,如BeanDefinitionRegistryPostProcessor對象方法的調(diào)用、BeanFactoryPostProcessor對象方法的調(diào)用以及Bean實例的創(chuàng)建都離不開這些BeanDefinition對象。

下面就來看看Spring是如何處理這些對象的。

正文

環(huán)境準(zhǔn)備

首先我們先回憶下refresh方法:

	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			//為容器初始化做準(zhǔn)備
			prepareRefresh();
			
			// 解析xml和注解
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 給BeanFacory設(shè)置屬性值以及添加一些處理器,即準(zhǔn)備Spring的上下文環(huán)境
			prepareBeanFactory(beanFactory);

			try {
				// 由子類實現(xiàn)對BeanFacoty的一些后置處理
				postProcessBeanFactory(beanFactory);


				/*
				* BeanDefinitionRegistryPostProcessor
				* BeanFactoryPostProcessor
				* 完成對這兩個接口的調(diào)用
				* */
				invokeBeanFactoryPostProcessors(beanFactory);

				/*
				* 把實現(xiàn)了BeanPostProcessor接口的類實例化,并且加入到BeanFactory中
				* */
				registerBeanPostProcessors(beanFactory);

				/*
				* 國際化
				* */
				initMessageSource();

				//初始化事件管理類
				initApplicationEventMulticaster();

				//這個方法著重理解模板設(shè)計模式,因為在springboot中,這個方法是用來做內(nèi)嵌tomcat啟動的
				onRefresh();

				/*
				* 往事件管理類中注冊事件類
				* */
				registerListeners();


				/*
				* 1、bean實例化過程
				* 2、依賴注入
				* 3、注解支持
				* 4、BeanPostProcessor的執(zhí)行
				* 5、Aop的入口
				*
				* */
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			} finally {
				resetCommonCaches();
			}
		}
	}

prepareBeanFactory和postProcessBeanFactory沒什么復(fù)雜的,關(guān)注一下里面設(shè)置了哪些值,添加了哪些對象就行,這些東西在后面的流程中會起到作用。

尤其是postProcessBeanFactory,這是一個模板方法,在其子類AbstractRefreshableWebApplicationContext中設(shè)置了兩個重要的標(biāo)識:

	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// 主要看著里面
		beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
		beanFactory.ignoreDependencyInterface(ServletContextAware.class);
		beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

		WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
		WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
	}

	public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
		Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
		// Remove from old position, if any
		this.beanPostProcessors.remove(beanPostProcessor);
		// Track whether it is instantiation/destruction aware
		if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
			this.hasInstantiationAwareBeanPostProcessors = true;
		}
		if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
			this.hasDestructionAwareBeanPostProcessors = true;
		}
		// Add to end of list
		this.beanPostProcessors.add(beanPostProcessor);
	}

分別將hasInstantiationAwareBeanPostProcessors、hasDestructionAwareBeanPostProcessors屬性都設(shè)置成了true,可以猜一下它們有什么作用。

兩個重要的Processor

在將上下文環(huán)境設(shè)置完成后,就是通過invokeBeanFactoryPostProcessors方法完成對BeanDefinitionRegistry以及BeanFactory的后置處理器的處理和調(diào)用,也就是依次調(diào)用BeanDefinitionRegistryPostProcessor接口和BeanFactoryPostProcessor接口的實現(xiàn)類。

我們可以通過實現(xiàn)這兩個接口在在BeanDefinition注冊完成后,對象實例化之前對容器中的BeanDefinition進(jìn)行動態(tài)的增刪查改,比如Spring中@Configuration注解的解析就是在這個過程中實現(xiàn)的。我們先來了解一下Spring內(nèi)置的Processor實現(xiàn)有哪些:

整個體系需要有個大概的印象,其中重點關(guān)注ConfigurationClassPostProcessor類,該類就是完成對@Configuration、@Bean等注解的解析注冊,這一塊的源碼這里暫時不分析。繼續(xù)開始的流程,進(jìn)入到

invokeBeanFactoryPostProcessors方法:

 protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
 // getBeanFactoryPostProcessors方法一般是獲取不到值的,除非我們手動調(diào)用addBeanFactoryPostProcessor方法添加進(jìn)去,
 // 換言之我們可以通過注解@Component或是手動調(diào)用addBeanFactoryPostProcessor方法來注入BeanFactoryPostProcessors對象
 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

 省略......
 }

這里面 通過委托模式調(diào)用PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法,并傳入了BeanFactory和Processors對象,但需要注意getBeanFactoryPostProcessors方法不是獲取通過xml配置和Component注解注冊到容器中的Processor對象,而是獲取通過調(diào)用AbstractApplicationContext.addBeanFactoryPostProcessor方法添加的類,換言之我們實現(xiàn)了Processor接口后可以不在類上添加@Component,直接調(diào)用addBeanFactoryPostProcessor方法即可,但需要注意,這種方式并沒有對應(yīng)的BeanDefinition類,添加的對象也不存在于IOC容器中。

繼續(xù)進(jìn)入invokeBeanFactoryPostProcessors方法:

	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			// 優(yōu)先處理通過addBeanFactoryPostProcessor方法添加的BeanFactoryPostProcessor
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				// 優(yōu)先處理BeanDefinitionRegistryPostProcessor對象
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}

			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			//獲取實現(xiàn)了BeanDefinitionRegistryPostProcessor接口的所有類的BeanDefinition對象的beanName
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				//判斷是否實現(xiàn)了排序接口 PriorityOrdered
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}

			//排序
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);

			//調(diào)用過程
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {

				//判斷是否是實現(xiàn)的Ordered接口
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			//沒實現(xiàn)排序接口的調(diào)用
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				//
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
				currentRegistryProcessors.clear();
			}

			//調(diào)用postProcessBeanFactory方法
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		//獲取實現(xiàn)了BeanFactoryPostProcessor接口的類,獲取beanDefinition的名稱
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
			}
			//實現(xiàn)了PriorityOrdered接口的
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			//實現(xiàn)了Ordered接口的
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				//沒實現(xiàn)接口的
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		//排序
		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);

		//調(diào)用
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		beanFactory.clearMetadataCache();
	}

這個方法很長,但邏輯并不復(fù)雜。首先判斷傳入的BeanFactory對象是不是BeanDefinitionRegistry對象,是的話則優(yōu)先調(diào)用傳入的Processor對象的postProcessBeanDefinitionRegistry方法,之后再通過beanFactory.getBeanNamesForType拿到容器中所有BeanDefinitionRegistryPostProcessor實現(xiàn)類的名字,然后依次實例化并調(diào)用實現(xiàn)了PriorityOrdered、Ordered接口(前者優(yōu)先級高于后者,數(shù)字越小優(yōu)先級越高)的Processor的postProcessBeanDefinitionRegistry方法,最后再實例化并調(diào)用剩余未實現(xiàn)排序接口的Processor的方法。當(dāng)所有BeanDefinitionRegistryPostProcessor實現(xiàn)類調(diào)用完成后,會依次調(diào)用來自于父接口BeanFactoryPostProcessor的postProcessBeanFactory方法。

上述流程處理完成后,又會通過beanFactory.getBeanNamesForType拿到容器中所有BeanFactoryPostProcessor實現(xiàn)類的名字,處理流程和上面一樣。

注冊BeanPostProcessor對象

以上就是兩個擴展點的調(diào)用流程,完成之后又會調(diào)用registerBeanPostProcessors注冊所有BeanPostProcessor的子類到容器中來,這個接口也是Spring的一個重要的擴展點,它包含了兩個方法:

 @Nullable
 default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
 return bean;
 }

 @Nullable
 default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
 return bean;
 }

實現(xiàn)了該接口的對象在實例化之前和之后分別會調(diào)用這兩個方法。同樣,我們先來了解下該接口的繼承體系:

可以看到這個接口Spring內(nèi)置的實現(xiàn)就比較多,可見用途之廣泛。另外上面畫紅框的是本次需要重點記憶的類,后面Bean實例化時會出現(xiàn)。接著我們來看看registerBeanPostProcessors的實現(xiàn)邏輯:

	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		//拿到工程里面所有實現(xiàn)了BeanPostProcessor接口的類,獲取到BeanDefinition的名稱
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();

		//提前實例化BeanPostProcessor類型的bean,然后bean進(jìn)行排序
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {

				//getBean是實例化方法,后面我們在講bean實例化過程是會著重講到
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);

				//判斷類型是否是MergedBeanDefinitionPostProcessor,如果是則代碼是內(nèi)部使用的
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);

		//注冊到BeanFactory中
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors.
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// Finally, re-register all internal BeanPostProcessors.
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

這段代碼的實現(xiàn)邏輯也很簡單,也是先區(qū)分優(yōu)先級,再獲取Bean實例,最后注冊到容器中,等到Bean實例化時調(diào)用。

接下來在refresh方法中調(diào)用了initMessageSource、initApplicationEventMulticaster、onRefresh、registerListeners,分別是初始化國際化資源、初始化時間廣播器、容器刷新事件(子類回調(diào))、注冊監(jiān)聽器,這幾個方法都很簡單,自己看看就行,這里就不詳細(xì)闡述了。

Bean對象的創(chuàng)建

當(dāng)所有的準(zhǔn)備工作都做好后,就該開始初始化Bean實例了,也就是finishBeanFactoryInitialization方法所做的事。不過這里可不是根據(jù)BeanDefinition new一個對象就完了,它包含了以下幾個工作:

1、初始化實例

2、解析@PostConstruct,@PreDestroy,@Resource, @Autowired,@Value等注解

3、依賴注入

4、調(diào)用BeanPostProcessor方法

5、AOP入口(本篇暫不分析)

下面就來詳細(xì)分析Bean實例化的整個流程:

	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		......
		
		//重點看這個方法
		// Instantiate all remaining (non-lazy-init) singletons.
		beanFactory.preInstantiateSingletons();
	}

	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("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.
		// xml解析時,講過,把所有beanName都緩存到beanDefinitionNames了
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			// 把父BeanDefinition里面的屬性拿到子BeanDefinition中
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

			//如果不是抽象的,單例的,非懶加載的就實例化
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {

				//判斷bean是否實現(xiàn)了FactoryBean接口,這里可以不看
				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 {
					//主要從這里進(jìn)入,看看實例化過程
					getBean(beanName);
				}
			}
		}
	}

在preInstantiateSingletons方法中可以看到這里有一個判斷:單例、非懶加載、非抽象,滿足這三個條件才會調(diào)用getBean(Bean實例化都是通過調(diào)用該方法實現(xiàn)的)實例化:

	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
	
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

		final String beanName = transformedBeanName(name);
		System.out.println("====beanName=="+beanName+"===instance begin====");
		Object bean;

			//從緩存中拿實例
		Object sharedInstance = getSingleton(beanName);
		//如果緩存里面能拿到實例
		if (sharedInstance != null && args == null) {
			// 該方法是FactoryBean接口的調(diào)用入口
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {

			//如果緩存里面沒有,則走下來
			//如果是scope 是Prototype的,校驗是否有出現(xiàn)循環(huán)依賴,如果有則直接報錯
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				// 父子BeanDefinition合并
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				// 檢驗是不是抽象類,是直接拋出異常
				checkMergedBeanDefinition(mbd, beanName, args);

				// 獲取依賴對象屬性,依賴對象要先實例化
				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						try {
							//實例化
							getBean(dep);
					}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				//大部分是單例的情況
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
					});
					// 該方法是FactoryBean接口的調(diào)用入口
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					// 該方法是FactoryBean接口的調(diào)用入口
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						// 該方法是FactoryBean接口的調(diào)用入口
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
				}
			}
		}

		return (T) bean;
	}

這段代碼首先從緩存里面拿到單例對象,如果沒有,則通過scope類型去創(chuàng)建對應(yīng)的Bean實例(直接創(chuàng)建或是通過getObjectForBeanInstance調(diào)用FactoryBean接口的方法創(chuàng)建)。在創(chuàng)建對象之前如果scope是prototype類型的首先會通過isPrototypeCurrentlyInCreation檢驗是否存在循環(huán)依賴(循環(huán)依賴這里先不講),存在直接拋出異常,原型對象不允許有循環(huán)依賴出現(xiàn);校驗完成后還會通過mbd.getDependsOn拿到@DependsOn注解的值,如果有,則會優(yōu)先實例化依賴的對象。

因為大部分都是創(chuàng)建單例對象,所以下面我以getSingleton方法來分析,需要注意該方法傳入了一個Lambda表達(dá)式,在該表達(dá)式中調(diào)用了createBean方法,觀察其它scope創(chuàng)建bean會發(fā)現(xiàn)都調(diào)用了該方法,所以實際創(chuàng)建bean對象就是該方法,不過我們還是先進(jìn)入getSingleton方法看看做了些什么:

	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			// 如果緩存中有,則直接返回
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}

				// 把beanName添加到singletonsCurrentlyInCreation Set容器中,在這個集合里面的bean都是正在實例化的bean
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					// 如果這里有返回值,就代表這個bean已經(jīng)結(jié)束創(chuàng)建了,已經(jīng)完全創(chuàng)建成功
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					//bean創(chuàng)建完成后singletonsCurrentlyInCreation要刪除該bean
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					System.out.println("====beanName==" + beanName + "===instance end====");
					// 創(chuàng)建對象成功時,把對象緩存到singletonObjects緩存中,bean創(chuàng)建完成時放入一級緩存
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

這個方法里面首先是從緩存中獲取對象,如果有直接返回,如果沒有則將該對象的beanName加入到singletonsCurrentlyInCreation緩存中,如果添加不成功,說明已經(jīng)有其它地方正在創(chuàng)建該對象,當(dāng)前創(chuàng)建直接拋出異常,如果添加成功,則調(diào)用singletonFactory.getObject去創(chuàng)建對象,這個方法就是傳入的Lambda表達(dá)式,創(chuàng)建完成后刪除掉singletonsCurrentlyInCreation緩存中的值并將對象添加到一級緩存,后續(xù)需要該對象時,都是從一級緩存中獲取的。

在getObject中通過createBean去創(chuàng)建對象,而該方法又調(diào)用了doCreateBean,我們直接來看這個方法:

	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			//創(chuàng)建實例,,重點看
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {

					// Bean實例化完成后收集類中的注解(@PostConstruct,@PreDestroy,@Resource, @Autowired,@Value)
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// 單例bean提前暴露
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			// 這里著重理解,對理解循環(huán)依賴幫助非常大,添加三級緩存
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			// ioc di,依賴注入的核心方法
			populateBean(beanName, mbd, instanceWrapper);

			// bean 實例化+ioc依賴注入完以后的調(diào)用
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			//注冊bean銷毀時的類DisposableBeanAdapter
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}

		return exposedObject;
	}

這個方法里面首先去通過createBeanInstance創(chuàng)建對象的實例,創(chuàng)建完成后又通過applyMergedBeanDefinitionPostProcessors收集類中的注解@Autowired、@Value、@PostConstruct,@PreDestroy,@Resource準(zhǔn)備依賴注入或是方法調(diào)用,緊接著調(diào)用addSingletonFactory添加三級緩存處理循環(huán)依賴,之后通過populateBean依賴注入真正完成一個完整對象的創(chuàng)建,最后在initializeBean中觸發(fā)事件和一些方法的調(diào)用。

下面逐個分析這些方法。

createBeanInstance

	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		//反射拿到Class對象
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		// 在xml配置bean時指定factory-bean屬性和factory-method以及@Bean注解
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Candidate constructors for autowiring?
		//尋找當(dāng)前正在實例化的bean中有@Autowired注解的構(gòu)造函數(shù)
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			//如果ctors不為空,就說明構(gòu)造函數(shù)上有@Autowired注解
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// Preferred constructors for default construction?
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		//無參構(gòu)造函數(shù)的實例化,大部分的實例是采用的無參構(gòu)造函數(shù)的方式實例化
		// No special handling: simply use no-arg constructor.
		return instantiateBean(beanName, mbd);
	}

在這個方法里面又做了很多判斷,首先是拿到factoryMethodName,當(dāng)我們在xml配置bean時指定了factory-bean屬性和factory-method屬性或者是使用了@Bean注解時這里就會拿到值,然后就會通過FactoryMethod去創(chuàng)建一個實例對象;如果不存在factoryMethodName,那么就需要通過構(gòu)造函數(shù)來實例化對象,但構(gòu)造函數(shù)上可能存在注解@Autowired,因此需要通過determineConstructorsFromBeanPostProcessors獲取到所有帶@Autowired注解的構(gòu)造函數(shù):

	protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
			throws BeansException {

		/**
		 * 通過AutowiredAnnotationBeanPostProcessor(在component-scan解析時
		 * 通過registerComponents方法注冊的,然后又在refresh中調(diào)用registerBeanPostProcessors方法
		 * 實例化的)類找到標(biāo)記了@Autowired注解的構(gòu)造函數(shù)
		 */
		if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
					if (ctors != null) {
						return ctors;
					}
				}
			}
		}
		return null;
	}

拿到所有帶@Autowired注解的構(gòu)造函數(shù)后就是通過調(diào)用autowireConstructor來進(jìn)行實例化,具體則是通過委托給ConstructorResolver類進(jìn)行處理,包括上面通過factoryMethod創(chuàng)建對象也是委托給這個類。如果沒有帶@Autowired的構(gòu)造函數(shù)才會調(diào)用instantiateBean方法,利用反射通過無參構(gòu)造函數(shù)去創(chuàng)建對象并返回,也是大部分對象實例化所走的流程。

至此,簡單對象的實例化完成。

addSingletonFactory

這個方法就是添加三級緩存解決循環(huán)依賴問題,暫時不分析。

populateBean

	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		boolean continueWithPropertyPopulation = true;

		// 這里可以寫接口可以讓所有類都不能依賴注入,沒有什么實際作用
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {

						//是否需要DI,依賴注入
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		if (!continueWithPropertyPopulation) {
			return;
		}

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;

		//重點看這個if代碼塊
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					//依賴注入過程,@Autowired的支持
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}

						//老版本用這個完成依賴注入過程,@Autowired的支持
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		// xml中<property>標(biāo)簽的依賴注入
		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

這里面主要有三個方法是完成依賴注入的:postProcessProperties(當(dāng)前主要使用)、postProcessPropertyValues(老版本廢棄API)、applyPropertyValues(xml中property標(biāo)簽)。

所以主要看看postProcessProperties方法,而這個方法又是來自于InstantiationAwareBeanPostProcessor接口(希望你還記得這個接口的繼承體系),主要看看AutowiredAnnotationBeanPostProcessor,這個就是解決@Autowired依賴注入的。

 public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
 InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
 try {
  metadata.inject(bean, beanName, pvs);
 }
 return pvs;
 }

見名知意,findAutowiringMetadata方法就是拿到@Autowired注解的屬性并封裝為InjectionMetadata對象,再調(diào)用inject進(jìn)行依賴注入,注意這里是包含了屬性和方法的(方法也不一定是setter方法才可以,只要是標(biāo)記了@Autowired且參數(shù)類型正確都能依賴成功)。

這就是@Autowired的注入過程,另外還有@Resource的注入,在CommonAnnotationBeanPostProcessor類中,流程和這個基本一樣,這里就不闡述了。

initializeBean

以上過程都是對Bean的實例化,以及對象中屬性的注入,都完成過后這個Bean對象才是我們真正可以直接使用的對象,所以接著就是處理一些方法的調(diào)用了(包含一些事件通知)。

	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			// 調(diào)用Aware方法
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			//對類中某些特殊方法的調(diào)用,比如@PostConstruct,Aware接口
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			//InitializingBean接口,afterPropertiesSet,init-method屬性調(diào)用,非常重要
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			// 這個地方可能生出代理實例,是aop的入口
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

	private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			// 實現(xiàn)該接口可以在bean實例化完成后獲取到bean的名稱
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}

			// 實現(xiàn)該接口可以在bean實例化完成后獲取到當(dāng)前的類加載器
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			// 實現(xiàn)該接口可以在bean實例化完成后獲取到當(dāng)前的AbstractAutowireCapableBeanFactory對象
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

首先是Aware接口的方法調(diào)用,這個很簡單不多說。接著就是applyBeanPostProcessorsBeforeInitialization方法調(diào)用,這個就是BeanPostProcessor接口的postProcessBeforeInitialization方法調(diào)用(看到這里你是否會發(fā)現(xiàn)自己之前理解錯了呢,以為該方法是在對象實例化之前調(diào)用,實際上也是實例化完成之后):

 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
  throws BeansException {

 Object result = existingBean;
 for (BeanPostProcessor processor : getBeanPostProcessors()) {
  Object current = processor.postProcessBeforeInitialization(result, beanName);
  if (current == null) {
  return result;
  }
  result = current;
 }
 return result;
 }

這里面著重看幾個實現(xiàn)類的調(diào)用:ApplicationContextAwareProcessor(ApplicationEventPublisherAware、ApplicationContextAware等Aware接口的調(diào)用)、InitDestroyAnnotationBeanPostProcessor(@PostConstruct注解方法的調(diào)用)、ImportAwareBeanPostProcessor(ImportAware類型實例setImportMetadata調(diào)用,對理解SpringBoot幫助很大,這里可以暫時不看)。

緊著著又通過invokeInitMethods方法調(diào)用InitializingBean接口的afterPropertiesSet方法以及init-method屬性配置的自定義初始化方法。

最后則是通過applyBeanPostProcessorsAfterInitialization方法調(diào)用BeanPostProcessor的postProcessAfterInitialization方法,因為涉及到AOP知識,這里不詳細(xì)分析。

至此,Bean的整個實例化過程分析完成,看到這里,你應(yīng)該對于Bean的生命周期函數(shù)有個基本的認(rèn)識了,最后放上我畫的Bean實例化流程時序圖:

總結(jié)

本篇篇幅很長,中間很多無關(guān)痛癢的代碼我都省略掉了,也有一些無關(guān)主流程但也比較重要的代碼沒有分析,比如ConfigurationClassPostProcessor解析@Configuration、@Bean注解的過程,F(xiàn)actoryMethod創(chuàng)建對象過程、獲取@Autowired注解標(biāo)記的構(gòu)造函數(shù)以及通過這些構(gòu)造函數(shù)實例化過程我都沒有分析,一來是限于篇幅過長,二來主要是因為對理解整個流程并沒有太大作用并且代碼相對更簡單,感興趣的讀者可在理解清楚主流程后自行分析。

相關(guān)文章

  • MyBatis簡介與配置MyBatis+Spring+MySql的方法

    MyBatis簡介與配置MyBatis+Spring+MySql的方法

    MyBatis 是一個可以自定義SQL、存儲過程和高級映射的持久層框架。這篇文章主要介紹了MyBatis簡介與配置MyBatis+Spring+MySql的方法,需要的朋友可以參考下
    2017-04-04
  • IDEA運行SpringBoot項目的詳細(xì)步驟(圖文教程)

    IDEA運行SpringBoot項目的詳細(xì)步驟(圖文教程)

    本文主要介紹了IDEA運行SpringBoot項目的詳細(xì)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • java如何獲取map中value的最大值

    java如何獲取map中value的最大值

    這篇文章主要介紹了java如何獲取map中value的最大值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • 細(xì)品Java8中hashCode方法的使用

    細(xì)品Java8中hashCode方法的使用

    這篇文章主要介紹了細(xì)品Java8中hashCode方法的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java中的interrupt、interrupted和isInterrupted方法區(qū)別詳解

    Java中的interrupt、interrupted和isInterrupted方法區(qū)別詳解

    這篇文章主要介紹了Java中的interrupt、interrupted和isInterrupted方法區(qū)別詳解,interrupt用于中斷線程,調(diào)用該方法的線程的狀態(tài)將會被設(shè)置為中斷狀態(tài),線程中斷僅僅是設(shè)置線程的中斷狀態(tài)位,并不會停止線程,需要用戶自己去監(jiān)視線程的狀態(tài)并作出處理,需要的朋友可以參考下
    2023-12-12
  • 詳解Java8中的lambda表達(dá)式、::符號和Optional類

    詳解Java8中的lambda表達(dá)式、::符號和Optional類

    這篇文章主要介紹了Java8中的lambda表達(dá)式、::符號和Optional類,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Java網(wǎng)絡(luò)編程UDP實現(xiàn)多線程在線聊天

    Java網(wǎng)絡(luò)編程UDP實現(xiàn)多線程在線聊天

    這篇文章主要為大家詳細(xì)介紹了Java網(wǎng)絡(luò)編程UDP實現(xiàn)多線程在線聊天,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • SpringCloudGateway網(wǎng)關(guān)處攔截并修改請求的操作方法

    SpringCloudGateway網(wǎng)關(guān)處攔截并修改請求的操作方法

    這篇文章主要介紹了SpringCloudGateway網(wǎng)關(guān)處攔截并修改請求的操作方法,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-12-12
  • Java編程guava RateLimiter實例解析

    Java編程guava RateLimiter實例解析

    這篇文章主要介紹了Java編程guava RateLimiter實例解析,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • 一文搞懂SpringMVC中@InitBinder注解的使用

    一文搞懂SpringMVC中@InitBinder注解的使用

    @InitBinder方法可以注冊控制器特定的java.bean.PropertyEditor或Spring Converter和 Formatter組件。本文通過示例為大家詳細(xì)講講@InitBinder注解的使用,需要的可以參考一下
    2022-06-06

最新評論