這一次搞懂Spring的Bean實(shí)例化原理操作
前言
前兩篇文章分析了Spring XML和注解的解析原理,并將其封裝為BeanDefinition對(duì)象存放到IOC容器中,而這些只是refresh方法中的其中一個(gè)步驟——obtainFreshBeanFactory,接下來(lái)就將圍繞著這些BeanDefinition對(duì)象進(jìn)行一系列的處理,如BeanDefinitionRegistryPostProcessor對(duì)象方法的調(diào)用、BeanFactoryPostProcessor對(duì)象方法的調(diào)用以及Bean實(shí)例的創(chuàng)建都離不開(kāi)這些BeanDefinition對(duì)象。
下面就來(lái)看看Spring是如何處理這些對(duì)象的。
正文
環(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 { // 由子類(lèi)實(shí)現(xiàn)對(duì)BeanFacoty的一些后置處理 postProcessBeanFactory(beanFactory); /* * BeanDefinitionRegistryPostProcessor * BeanFactoryPostProcessor * 完成對(duì)這兩個(gè)接口的調(diào)用 * */ invokeBeanFactoryPostProcessors(beanFactory); /* * 把實(shí)現(xiàn)了BeanPostProcessor接口的類(lèi)實(shí)例化,并且加入到BeanFactory中 * */ registerBeanPostProcessors(beanFactory); /* * 國(guó)際化 * */ initMessageSource(); //初始化事件管理類(lèi) initApplicationEventMulticaster(); //這個(gè)方法著重理解模板設(shè)計(jì)模式,因?yàn)樵趕pringboot中,這個(gè)方法是用來(lái)做內(nèi)嵌tomcat啟動(dòng)的 onRefresh(); /* * 往事件管理類(lèi)中注冊(cè)事件類(lèi) * */ registerListeners(); /* * 1、bean實(shí)例化過(guò)程 * 2、依賴(lài)注入 * 3、注解支持 * 4、BeanPostProcessor的執(zhí)行 * 5、Aop的入口 * * */ finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } finally { resetCommonCaches(); } } }
prepareBeanFactory和postProcessBeanFactory沒(méi)什么復(fù)雜的,關(guān)注一下里面設(shè)置了哪些值,添加了哪些對(duì)象就行,這些東西在后面的流程中會(huì)起到作用。
尤其是postProcessBeanFactory,這是一個(gè)模板方法,在其子類(lèi)AbstractRefreshableWebApplicationContext中設(shè)置了兩個(gè)重要的標(biāo)識(shí):
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,可以猜一下它們有什么作用。
兩個(gè)重要的Processor
在將上下文環(huán)境設(shè)置完成后,就是通過(guò)invokeBeanFactoryPostProcessors方法完成對(duì)BeanDefinitionRegistry以及BeanFactory的后置處理器的處理和調(diào)用,也就是依次調(diào)用BeanDefinitionRegistryPostProcessor接口和BeanFactoryPostProcessor接口的實(shí)現(xiàn)類(lèi)。
我們可以通過(guò)實(shí)現(xiàn)這兩個(gè)接口在在BeanDefinition注冊(cè)完成后,對(duì)象實(shí)例化之前對(duì)容器中的BeanDefinition進(jìn)行動(dòng)態(tài)的增刪查改,比如Spring中@Configuration注解的解析就是在這個(gè)過(guò)程中實(shí)現(xiàn)的。我們先來(lái)了解一下Spring內(nèi)置的Processor實(shí)現(xiàn)有哪些:
整個(gè)體系需要有個(gè)大概的印象,其中重點(diǎn)關(guān)注ConfigurationClassPostProcessor類(lèi),該類(lèi)就是完成對(duì)@Configuration、@Bean等注解的解析注冊(cè),這一塊的源碼這里暫時(shí)不分析。繼續(xù)開(kāi)始的流程,進(jìn)入到
invokeBeanFactoryPostProcessors方法: protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // getBeanFactoryPostProcessors方法一般是獲取不到值的,除非我們手動(dòng)調(diào)用addBeanFactoryPostProcessor方法添加進(jìn)去, // 換言之我們可以通過(guò)注解@Component或是手動(dòng)調(diào)用addBeanFactoryPostProcessor方法來(lái)注入BeanFactoryPostProcessors對(duì)象 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); 省略...... }
這里面 通過(guò)委托模式調(diào)用PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法,并傳入了BeanFactory和Processors對(duì)象,但需要注意getBeanFactoryPostProcessors方法不是獲取通過(guò)xml配置和Component注解注冊(cè)到容器中的Processor對(duì)象,而是獲取通過(guò)調(diào)用AbstractApplicationContext.addBeanFactoryPostProcessor方法添加的類(lèi),換言之我們實(shí)現(xiàn)了Processor接口后可以不在類(lèi)上添加@Component,直接調(diào)用addBeanFactoryPostProcessor方法即可,但需要注意,這種方式并沒(méi)有對(duì)應(yīng)的BeanDefinition類(lèi),添加的對(duì)象也不存在于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)先處理通過(guò)addBeanFactoryPostProcessor方法添加的BeanFactoryPostProcessor for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { // 優(yōu)先處理BeanDefinitionRegistryPostProcessor對(duì)象 if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); //獲取實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor接口的所有類(lèi)的BeanDefinition對(duì)象的beanName String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { //判斷是否實(shí)現(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)用過(guò)程 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { //判斷是否是實(shí)現(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(); //沒(méi)實(shí)現(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); } //獲取實(shí)現(xiàn)了BeanFactoryPostProcessor接口的類(lèi),獲取beanDefinition的名稱(chēng) 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 } //實(shí)現(xiàn)了PriorityOrdered接口的 else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } //實(shí)現(xiàn)了Ordered接口的 else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { //沒(méi)實(shí)現(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(); }
這個(gè)方法很長(zhǎng),但邏輯并不復(fù)雜。首先判斷傳入的BeanFactory對(duì)象是不是BeanDefinitionRegistry對(duì)象,是的話(huà)則優(yōu)先調(diào)用傳入的Processor對(duì)象的postProcessBeanDefinitionRegistry方法,之后再通過(guò)beanFactory.getBeanNamesForType拿到容器中所有BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類(lèi)的名字,然后依次實(shí)例化并調(diào)用實(shí)現(xiàn)了PriorityOrdered、Ordered接口(前者優(yōu)先級(jí)高于后者,數(shù)字越小優(yōu)先級(jí)越高)的Processor的postProcessBeanDefinitionRegistry方法,最后再實(shí)例化并調(diào)用剩余未實(shí)現(xiàn)排序接口的Processor的方法。當(dāng)所有BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類(lèi)調(diào)用完成后,會(huì)依次調(diào)用來(lái)自于父接口BeanFactoryPostProcessor的postProcessBeanFactory方法。
上述流程處理完成后,又會(huì)通過(guò)beanFactory.getBeanNamesForType拿到容器中所有BeanFactoryPostProcessor實(shí)現(xiàn)類(lèi)的名字,處理流程和上面一樣。
注冊(cè)BeanPostProcessor對(duì)象
以上就是兩個(gè)擴(kuò)展點(diǎn)的調(diào)用流程,完成之后又會(huì)調(diào)用registerBeanPostProcessors注冊(cè)所有BeanPostProcessor的子類(lèi)到容器中來(lái),這個(gè)接口也是Spring的一個(gè)重要的擴(kuò)展點(diǎn),它包含了兩個(gè)方法:
@Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; }
實(shí)現(xiàn)了該接口的對(duì)象在實(shí)例化之前和之后分別會(huì)調(diào)用這兩個(gè)方法。同樣,我們先來(lái)了解下該接口的繼承體系:
可以看到這個(gè)接口Spring內(nèi)置的實(shí)現(xiàn)就比較多,可見(jiàn)用途之廣泛。另外上面畫(huà)紅框的是本次需要重點(diǎn)記憶的類(lèi),后面Bean實(shí)例化時(shí)會(huì)出現(xiàn)。接著我們來(lái)看看registerBeanPostProcessors的實(shí)現(xiàn)邏輯:
public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { //拿到工程里面所有實(shí)現(xiàn)了BeanPostProcessor接口的類(lèi),獲取到BeanDefinition的名稱(chēng) 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<>(); //提前實(shí)例化BeanPostProcessor類(lèi)型的bean,然后bean進(jìn)行排序 for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { //getBean是實(shí)例化方法,后面我們?cè)谥vbean實(shí)例化過(guò)程是會(huì)著重講到 BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); //判斷類(lèi)型是否是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); //注冊(cè)到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)); }
這段代碼的實(shí)現(xiàn)邏輯也很簡(jiǎn)單,也是先區(qū)分優(yōu)先級(jí),再獲取Bean實(shí)例,最后注冊(cè)到容器中,等到Bean實(shí)例化時(shí)調(diào)用。
接下來(lái)在refresh方法中調(diào)用了initMessageSource、initApplicationEventMulticaster、onRefresh、registerListeners,分別是初始化國(guó)際化資源、初始化時(shí)間廣播器、容器刷新事件(子類(lèi)回調(diào))、注冊(cè)監(jiān)聽(tīng)器,這幾個(gè)方法都很簡(jiǎn)單,自己看看就行,這里就不詳細(xì)闡述了。
Bean對(duì)象的創(chuàng)建
當(dāng)所有的準(zhǔn)備工作都做好后,就該開(kāi)始初始化Bean實(shí)例了,也就是finishBeanFactoryInitialization方法所做的事。不過(guò)這里可不是根據(jù)BeanDefinition new一個(gè)對(duì)象就完了,它包含了以下幾個(gè)工作:
1、初始化實(shí)例
2、解析@PostConstruct,@PreDestroy,@Resource, @Autowired,@Value等注解
3、依賴(lài)注入
4、調(diào)用BeanPostProcessor方法
5、AOP入口(本篇暫不分析)
下面就來(lái)詳細(xì)分析Bean實(shí)例化的整個(gè)流程:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { ...... //重點(diǎn)看這個(gè)方法 // 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解析時(shí),講過(guò),把所有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); //如果不是抽象的,單例的,非懶加載的就實(shí)例化 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { //判斷bean是否實(shí)現(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)入,看看實(shí)例化過(guò)程 getBean(beanName); } } } }
在preInstantiateSingletons方法中可以看到這里有一個(gè)判斷:?jiǎn)卫?、非懶加載、非抽象,滿(mǎn)足這三個(gè)條件才會(huì)調(diào)用getBean(Bean實(shí)例化都是通過(guò)調(diào)用該方法實(shí)現(xiàn)的)實(shí)例化:
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; //從緩存中拿實(shí)例 Object sharedInstance = getSingleton(beanName); //如果緩存里面能拿到實(shí)例 if (sharedInstance != null && args == null) { // 該方法是FactoryBean接口的調(diào)用入口 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { //如果緩存里面沒(méi)有,則走下來(lái) //如果是scope 是Prototype的,校驗(yàn)是否有出現(xiàn)循環(huán)依賴(lài),如果有則直接報(bào)錯(cuò) 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); // 檢驗(yàn)是不是抽象類(lèi),是直接拋出異常 checkMergedBeanDefinition(mbd, beanName, args); // 獲取依賴(lài)對(duì)象屬性,依賴(lài)對(duì)象要先實(shí)例化 // 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 { //實(shí)例化 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; }
這段代碼首先從緩存里面拿到單例對(duì)象,如果沒(méi)有,則通過(guò)scope類(lèi)型去創(chuàng)建對(duì)應(yīng)的Bean實(shí)例(直接創(chuàng)建或是通過(guò)getObjectForBeanInstance調(diào)用FactoryBean接口的方法創(chuàng)建)。在創(chuàng)建對(duì)象之前如果scope是prototype類(lèi)型的首先會(huì)通過(guò)isPrototypeCurrentlyInCreation檢驗(yàn)是否存在循環(huán)依賴(lài)(循環(huán)依賴(lài)這里先不講),存在直接拋出異常,原型對(duì)象不允許有循環(huán)依賴(lài)出現(xiàn);校驗(yàn)完成后還會(huì)通過(guò)mbd.getDependsOn拿到@DependsOn注解的值,如果有,則會(huì)優(yōu)先實(shí)例化依賴(lài)的對(duì)象。
因?yàn)榇蟛糠侄际莿?chuàng)建單例對(duì)象,所以下面我以getSingleton方法來(lái)分析,需要注意該方法傳入了一個(gè)Lambda表達(dá)式,在該表達(dá)式中調(diào)用了createBean方法,觀察其它scope創(chuàng)建bean會(huì)發(fā)現(xiàn)都調(diào)用了該方法,所以實(shí)際創(chuàng)建bean對(duì)象就是該方法,不過(guò)我們還是先進(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容器中,在這個(gè)集合里面的bean都是正在實(shí)例化的bean beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { // 如果這里有返回值,就代表這個(gè)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要?jiǎng)h除該bean afterSingletonCreation(beanName); } if (newSingleton) { System.out.println("====beanName==" + beanName + "===instance end===="); // 創(chuàng)建對(duì)象成功時(shí),把對(duì)象緩存到singletonObjects緩存中,bean創(chuàng)建完成時(shí)放入一級(jí)緩存 addSingleton(beanName, singletonObject); } } return singletonObject; } }
這個(gè)方法里面首先是從緩存中獲取對(duì)象,如果有直接返回,如果沒(méi)有則將該對(duì)象的beanName加入到singletonsCurrentlyInCreation緩存中,如果添加不成功,說(shuō)明已經(jīng)有其它地方正在創(chuàng)建該對(duì)象,當(dāng)前創(chuàng)建直接拋出異常,如果添加成功,則調(diào)用singletonFactory.getObject去創(chuàng)建對(duì)象,這個(gè)方法就是傳入的Lambda表達(dá)式,創(chuàng)建完成后刪除掉singletonsCurrentlyInCreation緩存中的值并將對(duì)象添加到一級(jí)緩存,后續(xù)需要該對(duì)象時(shí),都是從一級(jí)緩存中獲取的。
在getObject中通過(guò)createBean去創(chuàng)建對(duì)象,而該方法又調(diào)用了doCreateBean,我們直接來(lái)看這個(gè)方法:
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)建實(shí)例,,重點(diǎn)看 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實(shí)例化完成后收集類(lèi)中的注解(@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"); } // 這里著重理解,對(duì)理解循環(huán)依賴(lài)幫助非常大,添加三級(jí)緩存 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { // ioc di,依賴(lài)注入的核心方法 populateBean(beanName, mbd, instanceWrapper); // bean 實(shí)例化+ioc依賴(lài)注入完以后的調(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 { //注冊(cè)bean銷(xiāo)毀時(shí)的類(lèi)DisposableBeanAdapter registerDisposableBeanIfNecessary(beanName, bean, mbd); } return exposedObject; }
這個(gè)方法里面首先去通過(guò)createBeanInstance創(chuàng)建對(duì)象的實(shí)例,創(chuàng)建完成后又通過(guò)applyMergedBeanDefinitionPostProcessors收集類(lèi)中的注解@Autowired、@Value、@PostConstruct,@PreDestroy,@Resource準(zhǔn)備依賴(lài)注入或是方法調(diào)用,緊接著調(diào)用addSingletonFactory添加三級(jí)緩存處理循環(huán)依賴(lài),之后通過(guò)populateBean依賴(lài)注入真正完成一個(gè)完整對(duì)象的創(chuàng)建,最后在initializeBean中觸發(fā)事件和一些方法的調(diào)用。
下面逐個(gè)分析這些方法。
createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // Make sure bean class is actually resolved at this point. //反射拿到Class對(duì)象 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時(shí)指定factory-bean屬性和factory-method以及@Bean注解 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // Candidate constructors for autowiring? //尋找當(dāng)前正在實(shí)例化的bean中有@Autowired注解的構(gòu)造函數(shù) Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { //如果ctors不為空,就說(shuō)明構(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); } //無(wú)參構(gòu)造函數(shù)的實(shí)例化,大部分的實(shí)例是采用的無(wú)參構(gòu)造函數(shù)的方式實(shí)例化 // No special handling: simply use no-arg constructor. return instantiateBean(beanName, mbd); }
在這個(gè)方法里面又做了很多判斷,首先是拿到factoryMethodName,當(dāng)我們?cè)趚ml配置bean時(shí)指定了factory-bean屬性和factory-method屬性或者是使用了@Bean注解時(shí)這里就會(huì)拿到值,然后就會(huì)通過(guò)FactoryMethod去創(chuàng)建一個(gè)實(shí)例對(duì)象;如果不存在factoryMethodName,那么就需要通過(guò)構(gòu)造函數(shù)來(lái)實(shí)例化對(duì)象,但構(gòu)造函數(shù)上可能存在注解@Autowired,因此需要通過(guò)determineConstructorsFromBeanPostProcessors獲取到所有帶@Autowired注解的構(gòu)造函數(shù):
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName) throws BeansException { /** * 通過(guò)AutowiredAnnotationBeanPostProcessor(在component-scan解析時(shí) * 通過(guò)registerComponents方法注冊(cè)的,然后又在refresh中調(diào)用registerBeanPostProcessors方法 * 實(shí)例化的)類(lèi)找到標(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ù)后就是通過(guò)調(diào)用autowireConstructor來(lái)進(jìn)行實(shí)例化,具體則是通過(guò)委托給ConstructorResolver類(lèi)進(jìn)行處理,包括上面通過(guò)factoryMethod創(chuàng)建對(duì)象也是委托給這個(gè)類(lèi)。如果沒(méi)有帶@Autowired的構(gòu)造函數(shù)才會(huì)調(diào)用instantiateBean方法,利用反射通過(guò)無(wú)參構(gòu)造函數(shù)去創(chuàng)建對(duì)象并返回,也是大部分對(duì)象實(shí)例化所走的流程。
至此,簡(jiǎn)單對(duì)象的實(shí)例化完成。
addSingletonFactory
這個(gè)方法就是添加三級(jí)緩存解決循環(huán)依賴(lài)問(wèn)題,暫時(shí)不分析。
populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { boolean continueWithPropertyPopulation = true; // 這里可以寫(xiě)接口可以讓所有類(lèi)都不能依賴(lài)注入,沒(méi)有什么實(shí)際作用 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { //是否需要DI,依賴(lài)注入 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; //重點(diǎn)看這個(gè)if代碼塊 if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; //依賴(lài)注入過(guò)程,@Autowired的支持 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } //老版本用這個(gè)完成依賴(lài)注入過(guò)程,@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)簽的依賴(lài)注入 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
這里面主要有三個(gè)方法是完成依賴(lài)注入的:postProcessProperties(當(dāng)前主要使用)、postProcessPropertyValues(老版本廢棄API)、applyPropertyValues(xml中property標(biāo)簽)。
所以主要看看postProcessProperties方法,而這個(gè)方法又是來(lái)自于InstantiationAwareBeanPostProcessor接口(希望你還記得這個(gè)接口的繼承體系),主要看看AutowiredAnnotationBeanPostProcessor,這個(gè)就是解決@Autowired依賴(lài)注入的。
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } return pvs; }
見(jiàn)名知意,findAutowiringMetadata方法就是拿到@Autowired注解的屬性并封裝為InjectionMetadata對(duì)象,再調(diào)用inject進(jìn)行依賴(lài)注入,注意這里是包含了屬性和方法的(方法也不一定是setter方法才可以,只要是標(biāo)記了@Autowired且參數(shù)類(lèi)型正確都能依賴(lài)成功)。
這就是@Autowired的注入過(guò)程,另外還有@Resource的注入,在CommonAnnotationBeanPostProcessor類(lèi)中,流程和這個(gè)基本一樣,這里就不闡述了。
initializeBean
以上過(guò)程都是對(duì)Bean的實(shí)例化,以及對(duì)象中屬性的注入,都完成過(guò)后這個(gè)Bean對(duì)象才是我們真正可以直接使用的對(duì)象,所以接著就是處理一些方法的調(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()) { //對(duì)類(lèi)中某些特殊方法的調(diào)用,比如@PostConstruct,Aware接口 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //InitializingBean接口,afterPropertiesSet,init-method屬性調(diào)用,非常重要 invokeInitMethods(beanName, wrappedBean, mbd); } if (mbd == null || !mbd.isSynthetic()) { // 這個(gè)地方可能生出代理實(shí)例,是aop的入口 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } private void invokeAwareMethods(final String beanName, final Object bean) { if (bean instanceof Aware) { // 實(shí)現(xiàn)該接口可以在bean實(shí)例化完成后獲取到bean的名稱(chēng) if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } // 實(shí)現(xiàn)該接口可以在bean實(shí)例化完成后獲取到當(dāng)前的類(lèi)加載器 if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } // 實(shí)現(xiàn)該接口可以在bean實(shí)例化完成后獲取到當(dāng)前的AbstractAutowireCapableBeanFactory對(duì)象 if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
首先是Aware接口的方法調(diào)用,這個(gè)很簡(jiǎn)單不多說(shuō)。接著就是applyBeanPostProcessorsBeforeInitialization方法調(diào)用,這個(gè)就是BeanPostProcessor接口的postProcessBeforeInitialization方法調(diào)用(看到這里你是否會(huì)發(fā)現(xiàn)自己之前理解錯(cuò)了呢,以為該方法是在對(duì)象實(shí)例化之前調(diào)用,實(shí)際上也是實(shí)例化完成之后):
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; }
這里面著重看幾個(gè)實(shí)現(xiàn)類(lèi)的調(diào)用:ApplicationContextAwareProcessor(ApplicationEventPublisherAware、ApplicationContextAware等Aware接口的調(diào)用)、InitDestroyAnnotationBeanPostProcessor(@PostConstruct注解方法的調(diào)用)、ImportAwareBeanPostProcessor(ImportAware類(lèi)型實(shí)例setImportMetadata調(diào)用,對(duì)理解SpringBoot幫助很大,這里可以暫時(shí)不看)。
緊著著又通過(guò)invokeInitMethods方法調(diào)用InitializingBean接口的afterPropertiesSet方法以及init-method屬性配置的自定義初始化方法。
最后則是通過(guò)applyBeanPostProcessorsAfterInitialization方法調(diào)用BeanPostProcessor的postProcessAfterInitialization方法,因?yàn)樯婕暗紸OP知識(shí),這里不詳細(xì)分析。
至此,Bean的整個(gè)實(shí)例化過(guò)程分析完成,看到這里,你應(yīng)該對(duì)于Bean的生命周期函數(shù)有個(gè)基本的認(rèn)識(shí)了,最后放上我畫(huà)的Bean實(shí)例化流程時(shí)序圖:
總結(jié)
本篇篇幅很長(zhǎng),中間很多無(wú)關(guān)痛癢的代碼我都省略掉了,也有一些無(wú)關(guān)主流程但也比較重要的代碼沒(méi)有分析,比如ConfigurationClassPostProcessor解析@Configuration、@Bean注解的過(guò)程,F(xiàn)actoryMethod創(chuàng)建對(duì)象過(guò)程、獲取@Autowired注解標(biāo)記的構(gòu)造函數(shù)以及通過(guò)這些構(gòu)造函數(shù)實(shí)例化過(guò)程我都沒(méi)有分析,一來(lái)是限于篇幅過(guò)長(zhǎng),二來(lái)主要是因?yàn)閷?duì)理解整個(gè)流程并沒(méi)有太大作用并且代碼相對(duì)更簡(jiǎn)單,感興趣的讀者可在理解清楚主流程后自行分析。
相關(guān)文章
MyBatis簡(jiǎn)介與配置MyBatis+Spring+MySql的方法
MyBatis 是一個(gè)可以自定義SQL、存儲(chǔ)過(guò)程和高級(jí)映射的持久層框架。這篇文章主要介紹了MyBatis簡(jiǎn)介與配置MyBatis+Spring+MySql的方法,需要的朋友可以參考下2017-04-04IDEA運(yùn)行SpringBoot項(xiàng)目的詳細(xì)步驟(圖文教程)
本文主要介紹了IDEA運(yùn)行SpringBoot項(xiàng)目的詳細(xì)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07Java中的interrupt、interrupted和isInterrupted方法區(qū)別詳解
這篇文章主要介紹了Java中的interrupt、interrupted和isInterrupted方法區(qū)別詳解,interrupt用于中斷線程,調(diào)用該方法的線程的狀態(tài)將會(huì)被設(shè)置為中斷狀態(tài),線程中斷僅僅是設(shè)置線程的中斷狀態(tài)位,并不會(huì)停止線程,需要用戶(hù)自己去監(jiān)視線程的狀態(tài)并作出處理,需要的朋友可以參考下2023-12-12詳解Java8中的lambda表達(dá)式、::符號(hào)和Optional類(lèi)
這篇文章主要介紹了Java8中的lambda表達(dá)式、::符號(hào)和Optional類(lèi),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04Java網(wǎng)絡(luò)編程UDP實(shí)現(xiàn)多線程在線聊天
這篇文章主要為大家詳細(xì)介紹了Java網(wǎng)絡(luò)編程UDP實(shí)現(xiàn)多線程在線聊天,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07SpringCloudGateway網(wǎng)關(guān)處攔截并修改請(qǐng)求的操作方法
這篇文章主要介紹了SpringCloudGateway網(wǎng)關(guān)處攔截并修改請(qǐng)求的操作方法,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-12-12Java編程guava RateLimiter實(shí)例解析
這篇文章主要介紹了Java編程guava RateLimiter實(shí)例解析,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01一文搞懂SpringMVC中@InitBinder注解的使用
@InitBinder方法可以注冊(cè)控制器特定的java.bean.PropertyEditor或Spring Converter和 Formatter組件。本文通過(guò)示例為大家詳細(xì)講講@InitBinder注解的使用,需要的可以參考一下2022-06-06