当前位置:

首页 > 编程开发 > SpringBoot源码之Bean的生命周期是什么

SpringBoot源码之Bean的生命周期是什么

入口方法为SpringApplication#run()1.SpringApplication#run()/***RuntheSpringapplication,creatingandrefreshinganew*{@linkApplicationContext}.*@paramargstheapplicationarguments(usuallypassedfromaJavamainmethod)*@returnarunning{@linkApplicationContext}*/publicConfi

本文目录

    入口方法为SpringApplication#run()

    1.SpringApplication#run()

    /**
    	 * Run the Spring application, creating and refreshing a new
    	 * {@link ApplicationContext}.
    	 * @param args the application arguments (usually passed from a Java main method)
    	 * @return a running {@link ApplicationContext}
    	 */
    	public ConfigurableApplicationContext run(String... args) {
    		long startTime = System.nanoTime();
    		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    		ConfigurableApplicationContext context = null;
    		configureHeadlessProperty();
    		SpringApplicationRunListeners listeners = getRunListeners(args);
    		listeners.starting(bootstrapContext, this.mainApplicationClass);
    		try {
    			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
    			Banner printedBanner = printBanner(environment);
    			context = createApplicationContext();
    			context.setApplicationStartup(this.applicationStartup);
    			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
    			refreshContext(context);
    			afterRefresh(context, applicationArguments);
    			Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
    			if (this.logStartupInfo) {
    				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
    			}
    			listeners.started(context, timeTakenToStartup);
    			callRunners(context, applicationArguments);
    		}
    		catch (Throwable ex) {
    			if (ex instanceof AbandonedRunException) {
    				throw ex;
    			}
    			handleRunFailure(context, ex, listeners);
    			throw new IllegalStateException(ex);
    		}
    		try {
    			if (context.isRunning()) {
    				Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
    				listeners.ready(context, timeTakenToReady);
    			}
    		}
    		catch (Throwable ex) {
    			if (ex instanceof AbandonedRunException) {
    				throw ex;
    			}
    			handleRunFailure(context, ex, null);
    			throw new IllegalStateException(ex);
    		}
    		return context;
    	}

    2.SpringApplication#run()=> SpringApplication#refreshContext(context)=> SpringApplication#refresh(context)=>ConfigurableApplicationContext#refresh()=>AbstractApplicationContext#refresh()

    @Override
    	public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
    			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
    
    			// Prepare this context for refreshing.
    			prepareRefresh();
    
    			// Tell the subclass to refresh the internal bean factory.
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    			// Prepare the bean factory for use in this context.
    			prepareBeanFactory(beanFactory);
    
    			try {
    				// Allows post-processing of the bean factory in context subclasses.
    				postProcessBeanFactory(beanFactory);
    
    				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
    				// Invoke factory processors registered as beans in the context.
    				invokeBeanFactoryPostProcessors(beanFactory);
    
    				// Register bean processors that intercept bean creation.
    				registerBeanPostProcessors(beanFactory);
    				beanPostProcess.end();
    
    				// Initialize message source for this context.
    				initMessageSource();
    
    				// Initialize event multicaster for this context.
    				initApplicationEventMulticaster();
    
    				// Initialize other special beans in specific context subclasses.
    				onRefresh();
    
    				// Check for listener beans and register them.
    				registerListeners();
    
    				// Instantiate all remaining (non-lazy-init) singletons.
    				finishBeanFactoryInitialization(beanFactory);
    
    				// Last step: publish corresponding event.
    				finishRefresh();
    			}
    
    			catch (BeansException ex) {
    				if (logger.isWarnEnabled()) {
    					logger.warn("Exception encountered during context initialization - " +
    							"cancelling refresh attempt: " + ex);
    				}
    
    				// Destroy already created singletons to avoid dangling resources.
    				destroyBeans();
    
    				// Reset 'active' flag.
    				cancelRefresh(ex);
    
    				// Propagate exception to caller.
    				throw ex;
    			}
    
    			finally {
    				// Reset common introspection caches in Spring's core, since we
    				// might not ever need metadata for singleton beans anymore...
    				resetCommonCaches();
    				contextRefresh.end();
    			}
    		}
    	}

    3.SpringApplication#run()=> SpringApplication#refreshContext(context)=> SpringApplication#refresh(context)=>ConfigurableApplicationContext#refresh()=>AbstractApplicationContext#refresh()=>AbstractApplicationContext#finishBeanFactoryInitialization()=>ConfigurableListableBeanFactory#preInstantiateSingletons()=>DefaultListableBeanFactory#preInstantiateSingletons()

    @Override
    	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.
    		List 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 SmartFactoryBean smartFactoryBean && smartFactoryBean.isEagerInit()) {
    						getBean(beanName);
    					}
    				}
    				else {
    					// 此处就是初始化bean的方法
    					getBean(beanName);
    				}
    			}
    		}
    
    		// Trigger post-initialization callback for all applicable beans...
    		for (String beanName : beanNames) {
    			// 此处就是解决循环依赖的代码
    			Object singletonInstance = getSingleton(beanName);
    			if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
    				StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
    						.tag("beanName", beanName);
    				smartSingleton.afterSingletonsInstantiated();
    				smartInitialize.end();
    			}
    		}
    	}

    解决循环依赖的代码如下:

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 尝试从缓存中获取成品的目标对象,如果存在,则直接返回
      Object singletonObject = this.singletonObjects.get(beanName);
      // 如果缓存中不存在目标对象,则判断当前对象是否已经处于创建过程中,在前面的讲解中,第一次尝试获取A对象
      // 的实例之后,就会将A对象标记为正在创建中,因而最后再尝试获取A对象的时候,这里的if判断就会为true
      if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
          singletonObject = this.earlySingletonObjects.get(beanName);
          if (singletonObject == null && allowEarlyReference) {
            // 这里的singletonFactories是一个Map,其key是bean的名称,而值是一个ObjectFactory类型的
            // 对象,这里对于A和B而言,调用图其getObject()方法返回的就是A和B对象的实例,无论是否是半成品
            ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
              // 获取目标对象的实例
              singletonObject = singletonFactory.getObject();
              this.earlySingletonObjects.put(beanName, singletonObject);
              this.singletonFactories.remove(beanName);
            }
          }
        }
      }
      return singletonObject;
    }
    • 一级缓存,singletonObjects 单例缓存,存储已经实例化的单例bean。

    • 二级缓存,earlySingletonObjects 提前暴露的单例缓存,这里存储的bean是刚刚构造完成,但还会通过属性注入bean。

    • 三级缓存,singletonFactories 生产单例的工厂缓存,存储工厂。

    解决原理如下:

    • 在第一层中,先去获取 A 的 Bean,发现没有就准备去创建一个,然后将 A 的代理工厂放入“三级缓存”(这个 A 其实是一个半成品,还没有对里面的属性进行注入),但是 A 依赖 B 的创建,就必须先去创建 B;

    • 在第二层中,准备创建 B,发现 B 又依赖 A,需要先去创建 A,去创建 A,因为第一层已经创建了 A 的代理工厂,直接从“三级缓存”中拿到 A 的代理工厂,获取 A 的代理对象,放入“二级缓存”,并清除“三级缓存”;

    • 有了 A 的代理对象,对 A 的依赖完美解决(这里的 A 仍然是个半成品),B 初始化成功。在 B 初始化成功,完成 A 对象的属性注入,然后再填充 A 的其它属性,以及 A 的其它步骤(包括 AOP),完成对 A 完整的初始化功能(这里的 A 才是完整的 Bean)。

    • 将 A 放入“一级缓存”。

    4.SpringApplication#run()=> SpringApplication#refreshContext(context)=> SpringApplication#refresh(context)=>ConfigurableApplicationContext#refresh()=>AbstractApplicationContext#refresh()=>AbstractApplicationContext#finishBeanFactoryInitialization()=>ConfigurableListableBeanFactory#preInstantiateSingletons()=>DefaultListableBeanFactory#preInstantiateSingletons()=>AbstractBeanFactory#getBean() => AbstractBeanFactory#doGetBean()=>AbstractBeanFactory#createBean()=>AbstractAutowireCapableBeanFactory#createBean()=>AbstractAutowireCapableBeanFactory#doCreateBean()

    bean的生命周期:

    1.调用InstantiationAwareBeanPostProcessor# postProcessBeforeInstantiation
    跟进doCreateBean()

    @Override  
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)  
          throws BeanCreationException {  
      
       if (logger.isTraceEnabled()) {  
          logger.trace("Creating instance of bean '" + beanName + "'");  
       }  
       RootBeanDefinition mbdToUse = mbd;  
      
       // Make sure bean class is actually resolved at this point, and  
       // clone the bean definition in case of a dynamically resolved Class   // which cannot be stored in the shared merged bean definition.   Class resolvedClass = resolveBeanClass(mbd, beanName);  
       if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {  
          mbdToUse = new RootBeanDefinition(mbd);  
          mbdToUse.setBeanClass(resolvedClass);  
       }  
      
       // Prepare method overrides.  
       try {  
          mbdToUse.prepareMethodOverrides();  
       }  
       catch (BeanDefinitionValidationException ex) {  
          throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),  
                beanName, "Validation of method overrides failed", ex);  
       }  
      
       try {  
          // 1.调用InstantiationAwareBeanPostProcessor# postProcessBeforeInstantiation
          Object bean = resolveBeforeInstantiation(beanName, mbdToUse);  
          if (bean != null) {  
             return bean;  
          }  
       }  
       catch (Throwable ex) {  
          throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,  
                "BeanPostProcessor before instantiation of bean failed", ex);  
       }  
      
       try {  
    	  // 跟进doCreateBean()
          Object beanInstance = doCreateBean(beanName, mbdToUse, args);  
          if (logger.isTraceEnabled()) {  
             logger.trace("Finished creating instance of bean '" + beanName + "'");  
          }  
          return beanInstance;  
       }  
       catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {  
          // A previously detected exception with proper bean creation context already,  
          // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.      throw ex;  
       }  
       catch (Throwable ex) {  
          throw new BeanCreationException(  
                mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);  
       }  
    }

    2.创建bean实例

    跟进populateBean()
    跟进initializeBean()

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)  
          throws BeanCreationException {  
      
       // Instantiate the bean.  
       BeanWrapper instanceWrapper = null;  
       if (mbd.isSingleton()) {  
          instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);  
       }  
       if (instanceWrapper == null) { 
    	  // 2.创建bean实例 
          instanceWrapper = createBeanInstance(beanName, mbd, args);  
       }  
       Object bean = instanceWrapper.getWrappedInstance();  
       Class beanType = instanceWrapper.getWrappedClass();  
       if (beanType != NullBean.class) {  
          mbd.resolvedTargetType = beanType;  
       }  
      
       // Allow post-processors to modify the merged bean definition.  
       synchronized (mbd.postProcessingLock) {  
          if (!mbd.postProcessed) {  
             try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);  
             }  
             catch (Throwable ex) {  
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
                      "Post-processing of merged bean definition failed", ex);  
             }  
             mbd.markAsPostProcessed();  
          }  
       }  
      
       // Eagerly cache singletons to be able to resolve circular references  
       // even when triggered by lifecycle interfaces like BeanFactoryAware.   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");  
          }  
          addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));  
       }  
      
       // Initialize the bean instance.  
       Object exposedObject = bean;  
       try {
    	  // 跟进populateBean()
          populateBean(beanName, mbd, instanceWrapper); 
          // 跟进initializeBean() 
          exposedObject = initializeBean(beanName, exposedObject, mbd);  
       }  
       catch (Throwable ex) {  
          if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {  
             throw bce;  
          }  
          else {  
             throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), 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 actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);  
                for (String dependentBean : dependentBeans) {  
                   if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {  
                      actualDependentBeans.add(dependentBean);  
                   }  
                }  
                if (!actualDependentBeans.isEmpty()) {  
                   throw new BeanCurrentlyInCreationException(beanName,  
                         "Bean with name '" + beanName + "' has been injected into other beans [" +  
                         StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +  
                         "] in its raw version as part of a circular reference, but has eventually been " +  
                         "wrapped. This means that said other beans do not use the final version of the " +  
                         "bean. This is often the result of over-eager type matching - consider using " +  
                         "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");  
                }  
             }  
          }  
       }  
      
       // Register bean as disposable.  
       try {  
          registerDisposableBeanIfNecessary(beanName, bean, mbd);  
       }  
       catch (BeanDefinitionValidationException ex) {  
          throw new BeanCreationException(  
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);  
       }  
      
       return exposedObject;  
    }

    3.调用InstantiationAwareBeanPostProcessor# postProcessAfterInstantiation

    4.注入bean属性

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {  
       if (bw == null) {  
          if (mbd.hasPropertyValues()) {  
             throw new BeanCreationException(  
                   mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");  
          }  
          else {  
             // Skip property population phase for null instance.  
             return;  
          }  
       }  
      
       if (bw.getWrappedClass().isRecord()) {  
          if (mbd.hasPropertyValues()) {  
             throw new BeanCreationException(  
                   mbd.getResourceDescription(), beanName, "Cannot apply property values to a record");  
          }  
          else {  
             // Skip property population phase for records since they are immutable.  
             return;  
          }  
       }  
      
          // 3.调用InstantiationAwareBeanPostProcessor# postProcessAfterInstantiation
          for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {  
             if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {  
                return;  
             }  
          }  
       }  
      
       PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);  
      
       int resolvedAutowireMode = mbd.getResolvedAutowireMode();  
       if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {  
          MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  
          // Add property values based on autowire by name if applicable.  
          if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {  
             autowireByName(beanName, mbd, bw, newPvs);  
          }  
          // Add property values based on autowire by type if applicable.  
          if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {  
             autowireByType(beanName, mbd, bw, newPvs);  
          }  
          pvs = newPvs;  
       }  
       if (hasInstantiationAwareBeanPostProcessors()) {  
          if (pvs == null) { 
             pvs = mbd.getPropertyValues();  
          }  
          for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {  
             PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);  
             if (pvsToUse == null) {  
                return;  
             }  
             pvs = pvsToUse;  
          }  
       }  
      
       boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);  
       if (needsDepCheck) {  
          PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);  
          checkDependencies(beanName, mbd, filteredPds, pvs);  
       }  
      
       if (pvs != null) {
    	  // 4.注入属性  
          applyPropertyValues(beanName, mbd, bw, pvs);  
       }  
    }

    5.设置Aware接口的属性

    6.调用BeanPostProcessor的初始化前置方法

    7.先((InitializingBean) bean).afterPropertiesSet(),后调用init-method方法,进行初始化操作

    8.调用BeanPostProcessor的初始化后置方法

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        // 5.设置Aware接口的属性
       invokeAwareMethods(beanName, bean);  
      
       Object wrappedBean = bean;  
       if (mbd == null || !mbd.isSynthetic()) {
    	  // 5.调用BeanPostProcessor的初始化前置方法  
          wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);  
       }  
      
       try {
    	  // 6.调用init-method方法,进行初始化操作  
          invokeInitMethods(beanName, wrappedBean, mbd);  
       }  
       catch (Throwable ex) {  
          throw new BeanCreationException(  
                (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);  
       }  
       if (mbd == null || !mbd.isSynthetic()) { 
          // 7. 调用BeanPostProcessor的初始化后置方法
          wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);  
       }  
      
       return wrappedBean;  
    }
    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发
    相关文章 更多
    EJB3.0部署消息驱动Bean抛javax.naming.NameNotFoundException异常
    EJB3.0部署消息驱动Bean抛javax.naming.NameNotFoundException异常

    部署消息驱动Bean时抛出javax.naming.NameNotFoundException异常,原因是JMS消息队列未在JNDI命名服务中注册。其解决方法为:需要手动配置一个Queue对象,例如在JBoss服务器中修改mail-service.xml或新建-service.xml文件,将Queue绑定至queue/myqueue路径。完成上述操作并重新部

    springBoot项目常用目录有哪些
    springBoot项目常用目录有哪些

    springBoot项目常用目录springBoot项目的目录结构及名规范介绍基于SpringBoot开发时的目录结构及命名规范,通过介绍能够为你解决,在实际项目中如何规划目录结构?如何命名目录更规范?各个目录分别代表什么含义?等三个问题。目录说明servicex//项目名|-admin-ui//管理服务前端代码(一般将UI和SERVICE放到一个工程中,便于管理)|-servicex-auth//模块1|-servicex-common//模块2|-servicex-gateway//模块3|-serv

    解析SpringBoot和SpringMVC之间的异同
    解析SpringBoot和SpringMVC之间的异同

    解析SpringBoot和SpringMVC之间的异同SpringBoot和SpringMVC是Java领域中非常重要的开发框架。虽然它们都属于Spring框架的一部分,但是在使用和功能上有一些明显的区别。本文将对SpringBoot和SpringMVC进行比较,解析它们之间的异同。首先,让我们来了解一下SpringBoot。SpringBo

    探索SpringCloud和SpringBoot在微服务领域的不同应用方式
    探索SpringCloud和SpringBoot在微服务领域的不同应用方式

    近年来,随着云计算和分布式架构的兴起,微服务架构的应用越来越广泛。而SpringCloud和SpringBoot作为Java开发中的两个重要框架,对于微服务的实现起到了重要的作用。然而,很多人对于它们在微服务领域的不同应用方式还存在一定的疑惑。本文将从不同的角度探索SpringCloud和SpringBoot在微服务中的应用方式。首先,我们来了解一下Spri

    SpringBoot和SpringMVC有何区别?
    SpringBoot和SpringMVC有何区别?

    SpringBoot与SpringMVC的不同之处在哪里?SpringBoot和SpringMVC是两个非常流行的Java开发框架,用于构建Web应用程序。尽管它们经常分别被使用,但它们之间的不同之处也是很明显的。首先,SpringBoot可以被看作是一个Spring框架的扩展或者增强版。它旨在简化Spring应用程序的初始化和配置过程,以帮助开发人

    比较SpringBoot和SpringMVC的异同
    比较SpringBoot和SpringMVC的异同

    SpringBoot和SpringMVC都是Java开发中常用的框架,但它们之间有一些明显的差异。本文将探究这两个框架的特点和用途,并对它们的差异进行比较。首先,我们来了解一下SpringBoot。SpringBoot是由Pivotal团队开发的,它旨在简化基于Spring框架的应用程序的创建和部署。它提供了一种快速、轻量级的方式来构建独立的、可执行

    SpringBoot与SpringMVC的不同点是什么?
    SpringBoot与SpringMVC的不同点是什么?

    SpringBoot和SpringMVC是Java开发中常用的两个框架,它们都是由Spring框架所提供的,但在功能和使用方式上有着一些区别。本文将分别介绍SpringBoot和SpringMVC的特点和区别。一、SpringBoot的特点:简化配置:SpringBoot通过约定优于配置的原则,大大简化了项目的配置过程。它可以自动配置项目所需要的参数,开发人

    比较和选择指南:SpringCloud与SpringBoot的功能比较
    比较和选择指南:SpringCloud与SpringBoot的功能比较

    SpringCloud和SpringBoot是目前Java领域中最热门的开源框架,它们分别提供了一套完善的微服务架构和快速构建应用程序的解决方案。本文将对它们的功能进行比较,并给出选择指南,以帮助读者了解它们的优势和适用场景。SpringBoot是一个用于开发Java应用程序的框架,它提供了一个简化的开发流程,集成了大量常用的功能和组件,减少了开发者的工作量

    Spring Bean的获取方式解析
    Spring Bean的获取方式解析

    Spring中Bean获取方式详解在Spring框架中,Bean的获取是非常重要的一环。在应用程序中,我们经常需要使用依赖注入或动态获取Bean的实例。本文将详细介绍Spring中Bean的获取方式,并给出具体的代码示例。通过@Component注解获取Bean@Component注解是Spring框架中常用的注解之一。我们可以通过在类上添加@Compone

    解析Spring中获取Bean的几种方式:深入理解与解析
    解析Spring中获取Bean的几种方式:深入理解与解析

    深入理解Spring:几种获取Bean的方式解析,需要具体代码示例Spring是一款非常流行的开源Java框架,它提供了丰富的功能和特性,其中一个重要的功能就是IoC(InversionofControl)即控制反转。在Spring中,Bean是作为应用程序的基本构建块之一,对Bean的获取方式也是Spring框架的关键点之一。在Spring中,我们可以

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。