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

Spring IOC 容器 refresh() 方法

 更新時(shí)間:2026年05月23日 09:33:32   作者:明夜之約  
Spring容器的refresh()方法是其啟動(dòng)的核心入口,由1個(gè)標(biāo)準(zhǔn)步驟,完成從配置加載到Bean實(shí)例化的全流程,這篇文章給大家介紹Spring IOC 容器 refresh()方法,感興趣的朋友跟隨小編一起看看吧

Spring IOC 容器的 refresh() 方法是容器啟動(dòng)的核心入口,包含 12 個(gè)標(biāo)準(zhǔn)步驟,負(fù)責(zé)完成從配置加載到 Bean 實(shí)例化的全流程。

整體流程是什么

refresh() 方法在 AbstractApplicationContext 中定義,采用模板方法模式,確保容器初始化過程線程安全。12 個(gè)步驟按順序執(zhí)行:

  • 準(zhǔn)備階段‌:prepareRefresh() 記錄啟動(dòng)時(shí)間、設(shè)置活躍標(biāo)志。
  • 工廠獲取‌:obtainFreshBeanFactory() 創(chuàng)建或刷新 BeanFactory。
  • 工廠配置‌:prepareBeanFactory() 設(shè)置類加載器、表達(dá)式解析器等基礎(chǔ)設(shè)施。
  • 后置處理‌:postProcessBeanFactory() 留給子類擴(kuò)展的空實(shí)現(xiàn)。
  • 處理器調(diào)用‌:invokeBeanFactoryPostProcessors() 執(zhí)行配置類后置處理器。
  • 處理器注冊(cè)‌:registerBeanPostProcessors() 注冊(cè) Bean 實(shí)例化前后攔截器。
  • 消息源初始化‌:initMessageSource() 處理國(guó)際化資源。
  • 事件廣播器‌:initApplicationEventMulticaster() 建立事件發(fā)布機(jī)制。
  • 子類擴(kuò)展‌:onRefresh() 模板方法供 Web 容器等初始化特定功能。
  • 監(jiān)聽器注冊(cè)‌:registerListeners() 添加應(yīng)用事件監(jiān)聽器。
  • Bean 初始化‌:finishBeanFactoryInitialization() 實(shí)例化所有非懶加載單例。
  • 刷新完成‌:finishRefresh() 發(fā)布容器刷新完成事件。‌‌‌

Spring IOC 容器 refresh() 方法的 12 個(gè)標(biāo)準(zhǔn)步驟逐行解析

標(biāo)簽:Spring | IOC | refresh | Bean 生命周期

一、問題引入

// 我們每天都在用的 Spring Boot 啟動(dòng)
SpringApplication.run(MyApp.class, args);
// 其底層最終調(diào)用的是:
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();  // ← 一切魔法從這里開始

refresh() 方法是 Spring Framework 最核心的方法之一。從配置文件加載、Bean 定義注冊(cè)到單例預(yù)實(shí)例化,整個(gè) Spring 容器的生命周期都在這里完成。本文逐行解析 refresh() 的 12 個(gè)標(biāo)準(zhǔn)步驟。

二、refresh()方法全貌

// org.springframework.context.support.AbstractApplicationContext
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
        // 步驟 1: 準(zhǔn)備刷新
        prepareRefresh();
        // 步驟 2: 獲取/刷新 BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // 步驟 3: 準(zhǔn)備 BeanFactory
        prepareBeanFactory(beanFactory);
        try {
            // 步驟 4: 子類擴(kuò)展的 BeanFactory 后處理
            postProcessBeanFactory(beanFactory);
            StartupStep beanPostProcess = this.applicationStartup.start(
                "spring.context.beans.post-process");
            // 步驟 5: 執(zhí)行 BeanFactoryPostProcessor
            invokeBeanFactoryPostProcessors(beanFactory);
            // 步驟 6: 注冊(cè) BeanPostProcessor
            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();
            // 步驟 7: 初始化消息源
            initMessageSource();
            // 步驟 8: 初始化事件廣播器
            initApplicationEventMulticaster();
            // 步驟 9: 子類擴(kuò)展的初始化邏輯
            onRefresh();
            // 步驟 10: 注冊(cè)監(jiān)聽器
            registerListeners();
            // 步驟 11: 實(shí)例化所有非延遲單例 Bean
            finishBeanFactoryInitialization(beanFactory);
            // 步驟 12: 完成刷新,發(fā)布事件
            finishRefresh();
        }
        // ... 異常處理
    }
}

三、12 步驟逐行解析

步驟 1:prepareRefresh()—— 準(zhǔn)備刷新

protected void prepareRefresh() {
    // 記錄啟動(dòng)時(shí)間
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);
    // 初始化屬性源(如 @PropertySource 指定的配置文件)
    initPropertySources();
    // 驗(yàn)證必需的環(huán)境變量是否都存在
    getEnvironment().validateRequiredProperties();
    // 初始化早期應(yīng)用監(jiān)聽器
    if (this.earlyApplicationListeners == null) {
        this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
}

核心職責(zé):環(huán)境準(zhǔn)備 + 狀態(tài)切換 + 屬性驗(yàn)證。

步驟 2:obtainFreshBeanFactory()—— 獲取 BeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 子類實(shí)現(xiàn):創(chuàng)建或刷新內(nèi)部的 BeanFactory
    refreshBeanFactory();
    // 返回 freshly created BeanFactory
    return getBeanFactory();
}

AnnotationConfigApplicationContext 的實(shí)現(xiàn)

@Override
protected final void refreshBeanFactory() throws BeansException {
    // 如果有舊的 BeanFactory,銷毀所有 Bean 并關(guān)閉
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 創(chuàng)建新的 DefaultListableBeanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        // 加載 Bean 定義(@Configuration 類解析)
        loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    } catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source", ex);
    }
}

DefaultListableBeanFactory 是 Spring 最核心的 BeanFactory 實(shí)現(xiàn):

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {
    // Bean 定義的注冊(cè)表:key=beanName, value=BeanDefinition
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    // 單例 Bean 的緩存池
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    // 按類型索引的 Bean 名稱
    private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
}

步驟 3:prepareBeanFactory()—— 準(zhǔn)備 BeanFactory

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 設(shè)置類加載器
    beanFactory.setBeanClassLoader(getClassLoader());
    // 添加 SpEL 表達(dá)式解析器(@Value("${app.name}") 的解析)
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
    // 添加屬性編輯器注冊(cè)器(String → Date 等類型轉(zhuǎn)換)
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    // 添加 BeanPostProcessor:ApplicationContextAwareProcessor
    // 處理 Aware 接口:ApplicationContextAware, EnvironmentAware, ResourceLoaderAware
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 忽略以下依賴接口的自動(dòng)裝配(由 ApplicationContextAwareProcessor 處理)
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    // 注冊(cè)可解析的依賴類型:注入時(shí)自動(dòng)映射到當(dāng)前對(duì)象
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    // 注冊(cè)早期后置處理器:檢測(cè) ApplicationListener 類型的 Bean
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    // 檢測(cè) LoadTimeWeaver(AOP 加載時(shí)織入)
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
    // 注冊(cè)默認(rèn)環(huán)境 Bean(如果用戶未定義)
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

核心職責(zé):注冊(cè)內(nèi)置的 BeanPostProcessor + 配置自動(dòng)裝配規(guī)則 + 注冊(cè)環(huán)境 Bean。

步驟 4:postProcessBeanFactory()—— BeanFactory 后處理(子類擴(kuò)展)

// AbstractApplicationContext 中為空實(shí)現(xiàn),子類可覆蓋
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
// AnnotationConfigApplicationContext 的擴(kuò)展:
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    super.postProcessBeanFactory(beanFactory);
    // 添加 ConfigurationClassPostProcessor 的回調(diào)
    if (this.basePackages != null && this.basePackages.length > 0) {
        // 掃描 @Component 類并注冊(cè) Bean 定義
        this.scanner.scan(this.basePackages);
    }
    if (!this.annotatedClasses.isEmpty()) {
        // 注冊(cè) @Configuration 類
        this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
    }
}

步驟 5:invokeBeanFactoryPostProcessors()—— 執(zhí)行 BeanFactory 后置處理器

這是最重要的步驟之一——處理 @Configuration 類、解析 @Bean 方法、處理 @PropertySource/@ComponentScan/@Import。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, 
        getBeanFactoryPostProcessors());
}

處理順序(嚴(yán)格按優(yōu)先級(jí)):

1. BeanDefinitionRegistryPostProcessor (繼承 BeanFactoryPostProcessor)
   └─ ConfigurationClassPostProcessor  ← 最重要!處理 @Configuration
       ├─ 解析 @ComponentScan → 掃描包下的 @Component
       ├─ 解析 @Import → 處理 @EnableAutoConfiguration
       ├─ 解析 @ImportResource → 加載 XML 配置
       ├─ 解析 @Bean → 注冊(cè)方法返回值為 Bean
       └─ 解析 @PropertySource → 加載屬性文件
2. 常規(guī)的 BeanFactoryPostProcessor
   └─ PropertySourcesPlaceholderConfigurer  ← 處理 ${...} 占位符

ConfigurationClassPostProcessor 的核心流程:

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        // 1. 從注冊(cè)表中找出所有 @Configuration 類
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        for (String beanName : registry.getBeanDefinitionNames()) {
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }
        // 2. 解析每個(gè) @Configuration 類
        ConfigurationClassParser parser = new ConfigurationClassParser(...);
        parser.parse(configCandidates);
        // 3. 讀取解析結(jié)果,注冊(cè)新的 Bean 定義
        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        ConfigurationClassBeanDefinitionReader reader = new ConfigurationClassBeanDefinitionReader(...);
        reader.loadBeanDefinitions(configClasses);
    }
}

步驟 6:registerBeanPostProcessors()—— 注冊(cè) Bean 后置處理器

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

注冊(cè)順序(按 Ordered/PriorityOrdered 排序):

1. PriorityOrdered 的 BeanPostProcessor
   └─ AutowiredAnnotationBeanPostProcessor  ← 處理 @Autowired
   └─ CommonAnnotationBeanPostProcessor     ← 處理 @PostConstruct, @PreDestroy, @Resource
2. Ordered 的 BeanPostProcessor
3. 普通的 BeanPostProcessor
   └─ AsyncAnnotationBeanPostProcessor     ← 處理 @Async
   └─ ScheduledAnnotationBeanPostProcessor ← 處理 @Scheduled
   └─ TransactionProxyFactoryBean          ← 處理 @Transactional
   └─ AOP 相關(guān)的 BeanPostProcessor         ← 處理 @Aspect
4. ApplicationListenerDetector(內(nèi)部使用)

AutowiredAnnotationBeanPostProcessor 的注入時(shí)機(jī):

public class AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        // 1. 查找 @Autowired 標(biāo)注的字段/方法
        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        // 2. 執(zhí)行注入
        metadata.inject(bean, beanName, pvs);
        return pvs;
    }
}

步驟 7:initMessageSource()—— 初始化消息源

protected void initMessageSource() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
        // 用戶自定義了 MessageSource
        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
    } else {
        // 使用默認(rèn)的 DelegatingMessageSource
        DelegatingMessageSource dms = new DelegatingMessageSource();
        dms.setParentMessageSource(getInternalParentMessageSource());
        this.messageSource = dms;
        beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
    }
}

步驟 8:initApplicationEventMulticaster()—— 初始化事件廣播器

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster = beanFactory.getBean(
            APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
    } else {
        // 默認(rèn)使用 SimpleApplicationEventMulticaster
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, 
            this.applicationEventMulticaster);
    }
}

步驟 9:onRefresh()—— 子類擴(kuò)展(創(chuàng)建內(nèi)嵌 Web 服務(wù)器)

// AbstractApplicationContext 中為空實(shí)現(xiàn)
protected void onRefresh() throws BeansException {
}
// ServletWebServerApplicationContext 的擴(kuò)展:
@Override
protected void onRefresh() {
    super.onRefresh();
    try {
        // 創(chuàng)建內(nèi)嵌 Tomcat/Jetty/Undertow
        createWebServer();
    } catch (Throwable ex) {
        throw new ApplicationContextException("Unable to start web server", ex);
    }
}
private void createWebServer() {
    WebServer webServer = this.webServer;
    ServletContext servletContext = getServletContext();
    if (webServer == null && servletContext == null) {
        // 從 BeanFactory 獲取 WebServerFactory
        ServletWebServerFactory factory = getWebServerFactory();
        // 創(chuàng)建 WebServer(如 TomcatWebServer)
        this.webServer = factory.getWebServer(getSelfInitializer());
    }
}

Spring Boot 內(nèi)嵌 Tomcat 的創(chuàng)建就是在這里完成的!

步驟 10:registerListeners()—— 注冊(cè)監(jiān)聽器

protected void registerListeners() {
    // 注冊(cè)靜態(tài)指定的監(jiān)聽器
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }
    // 從 BeanFactory 獲取所有 ApplicationListener 類型的 Bean
    String[] listenerBeanNames = getBeanFactoryNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }
    // 發(fā)布早期累積的事件
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

步驟 11:finishBeanFactoryInitialization()—— 實(shí)例化所有非延遲單例 Bean

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 轉(zhuǎn)換服務(wù)(String → Integer 等類型轉(zhuǎn)換)
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> 
            getEnvironment().resolvePlaceholders(strVal));
    }
    // 初始化 LoadTimeWeaverAware Bean
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, 
        false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    // 停止使用臨時(shí)類加載器
    beanFactory.setTempClassLoader(null);
    // 凍結(jié)配置(不允許再修改 Bean 定義)
    beanFactory.freezeConfiguration();
    // ★★★ 實(shí)例化所有非延遲單例 Bean ★★★
    beanFactory.preInstantiateSingletons();
}

preInstantiateSingletons() 是核心:

@Override
public void preInstantiateSingletons() throws BeansException {
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    // 觸發(fā)所有非延遲單例 Bean 的實(shí)例化
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        // 非抽象 && 單例 && 非延遲初始化
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) {
                // FactoryBean 特殊處理
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            } else {
                // ★ 普通 Bean 的獲取 → 觸發(fā)創(chuàng)建
                getBean(beanName);
            }
        }
    }
    // 觸發(fā) SmartInitializingSingleton 回調(diào)
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            ((SmartInitializingSingleton) singletonInstance).afterSingletonsInstantiated();
        }
    }
}

步驟 12:finishRefresh()—— 完成刷新

protected void finishRefresh() {
    // 清除上下文級(jí)資源緩存
    clearResourceCaches();
    // 初始化 LifecycleProcessor
    initLifecycleProcessor();
    // 啟動(dòng)所有實(shí)現(xiàn)了 Lifecycle 接口的 Bean
    getLifecycleProcessor().onRefresh();
    // ★ 發(fā)布 ContextRefreshedEvent 事件 ★
    publishEvent(new ContextRefreshedEvent(this));
    // LiveBeansView MBean 注冊(cè)(JMX 監(jiān)控)
    LiveBeansView.registerApplicationContext(this);
}

ContextRefreshedEvent 是應(yīng)用啟動(dòng)完成的標(biāo)志,很多框架(如 Dubbo)監(jiān)聽此事件完成服務(wù)暴露。

四、12 步驟總結(jié)圖

┌─────────────────────────────────────────────────────┐
│              refresh() 12 步驟                       │
├─────────────────────────────────────────────────────┤
│ 1. prepareRefresh()           環(huán)境準(zhǔn)備 + 狀態(tài)校驗(yàn)     │
│ 2. obtainFreshBeanFactory()   創(chuàng)建 BeanFactory       │
│ 3. prepareBeanFactory()       注冊(cè)內(nèi)置 BPP           │
│ 4. postProcessBeanFactory()   子類擴(kuò)展(掃描)        │
│ 5. invokeBeanFactoryPostProcessors() @Configuration  │
│ 6. registerBeanPostProcessors() 注冊(cè) @Autowired/AOP  │
│ 7. initMessageSource()        國(guó)際化                 │
│ 8. initApplicationEventMulticaster() 事件廣播器      │
│ 9. onRefresh()                子類(創(chuàng)建 WebServer) │
│ 10. registerListeners()       注冊(cè) @EventListener    │
│ 11. finishBeanFactoryInitialization() 實(shí)例化單例      │
│ 12. finishRefresh()           發(fā)布刷新完成事件        │
└─────────────────────────────────────────────────────┘
         ↓
    Application Ready!

到此這篇關(guān)于Spring IOC 容器 refresh() 方法的文章就介紹到這了,更多相關(guān)Spring IOC 容器 refresh() 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 教你怎么用Springboot自定義Banner圖案

    教你怎么用Springboot自定義Banner圖案

    今天給大家?guī)淼氖荍ava的相關(guān)知識(shí),文章圍繞著怎么用Springboot自定義Banner圖案展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 為什么wait和notify必須放在synchronized中使用

    為什么wait和notify必須放在synchronized中使用

    這篇文章主要介紹了為什么wait和notify必須放在synchronized中使用,文章圍繞主題的相關(guān)問題展開詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考以參考一下
    2022-05-05
  • 使用jackson實(shí)現(xiàn)對(duì)象json之間的相互轉(zhuǎn)換(spring boot)

    使用jackson實(shí)現(xiàn)對(duì)象json之間的相互轉(zhuǎn)換(spring boot)

    這篇文章主要介紹了使用jackson實(shí)現(xiàn)對(duì)象json之間的相互轉(zhuǎn)換(spring boot),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java復(fù)制一個(gè)對(duì)象并且不想復(fù)制其中的空值屬性問題

    Java復(fù)制一個(gè)對(duì)象并且不想復(fù)制其中的空值屬性問題

    這篇文章主要介紹了Java復(fù)制一個(gè)對(duì)象并且不想復(fù)制其中的空值屬性問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 2個(gè)java希爾排序示例

    2個(gè)java希爾排序示例

    java希爾排序示例,希爾排序是插入排序的一種類型,也可以用一個(gè)形象的叫法縮小增量法,需要的朋友可以參考下
    2014-05-05
  • Hibernate框架數(shù)據(jù)分頁技術(shù)實(shí)例分析

    Hibernate框架數(shù)據(jù)分頁技術(shù)實(shí)例分析

    這篇文章主要介紹了Hibernate框架數(shù)據(jù)分頁技術(shù),結(jié)合實(shí)例形式分析了Hibernate框架實(shí)現(xiàn)數(shù)據(jù)分頁的原理,步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-03-03
  • Java?JDK17和Maven安裝教程圖文詳解

    Java?JDK17和Maven安裝教程圖文詳解

    JDK 17是Java平臺(tái)的一個(gè)長(zhǎng)期支持版本,它包含了一系列新的功能和改進(jìn) JDK 17還包括一些其他改進(jìn),這篇文章主要介紹了Java?JDK17和Maven安裝教程的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2025-12-12
  • 關(guān)于junit單元測(cè)試@Test的使用方式

    關(guān)于junit單元測(cè)試@Test的使用方式

    這篇文章主要介紹了關(guān)于junit單元測(cè)試@Test的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • IDEA斷點(diǎn)調(diào)試,斷點(diǎn)不起作用的解決

    IDEA斷點(diǎn)調(diào)試,斷點(diǎn)不起作用的解決

    這篇文章主要介紹了IDEA斷點(diǎn)調(diào)試,斷點(diǎn)不起作用的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 簡(jiǎn)述IDEA集成Git在實(shí)際項(xiàng)目中的運(yùn)用

    簡(jiǎn)述IDEA集成Git在實(shí)際項(xiàng)目中的運(yùn)用

    這篇文章主要介紹了IDEA集成Git在實(shí)際項(xiàng)目中的運(yùn)用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-07-07

最新評(píng)論

山丹县| 雷山县| 团风县| 延吉市| 弥渡县| 兴义市| 韶关市| 拉萨市| 宁武县| 惠水县| 双牌县| 丘北县| 新巴尔虎左旗| 诏安县| 独山县| 彭阳县| 晋中市| 大安市| 通辽市| 深泽县| 环江| 宽甸| 格尔木市| 汕尾市| 四川省| 壤塘县| 滨州市| 赣榆县| 汝州市| 南岸区| 桂林市| 滨海县| 左权县| 西峡县| 汝阳县| 白玉县| 吴桥县| 陇西县| 沙坪坝区| 太仓市| 玛沁县|