欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot啟動(dòng)流程之引導(dǎo)上下文DefaultBootstrapContext的過程

 更新時(shí)間:2024年11月04日 15:06:37   作者:冬天vs不冷  
本文詳細(xì)介紹了SpringBoot版本2.7.18中SpringApplication的run方法,引導(dǎo)注冊組件初始化器BootstrapRegistryInitializer是SpringBoot的第一個(gè)擴(kuò)展點(diǎn),負(fù)責(zé)應(yīng)用啟動(dòng)早期階段的初始化和配置,感興趣的朋友跟隨小編一起看看吧

前言

  前文深入解析SpringApplication構(gòu)造方法,而接下來的幾篇文章將重點(diǎn)介紹run方法的執(zhí)行邏輯。

SpringBoot版本2.7.18的SpringApplication的run方法的執(zhí)行邏輯如下,本文將詳細(xì)介紹第一小節(jié):創(chuàng)建引導(dǎo)上下文

// SpringApplication類方法
public ConfigurableApplicationContext run(String... args) {
    // 記錄應(yīng)用啟動(dòng)的開始時(shí)間
    long startTime = System.nanoTime();
    // 1.創(chuàng)建引導(dǎo)上下文,用于管理應(yīng)用啟動(dòng)時(shí)的依賴和資源
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    ConfigurableApplicationContext context = null;
    // 配置無頭模式屬性,以支持在無圖形環(huán)境下運(yùn)行
    // 將系統(tǒng)屬性 java.awt.headless 設(shè)置為 true
    configureHeadlessProperty();
    // 2.獲取Spring應(yīng)用啟動(dòng)監(jiān)聽器,用于在應(yīng)用啟動(dòng)的各個(gè)階段執(zhí)行自定義邏輯
    SpringApplicationRunListeners listeners = getRunListeners(args);
    // 3.發(fā)布開始事件、通知ApplicationListener監(jiān)聽器
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    try {
        // 4.解析應(yīng)用參數(shù)
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // 5.準(zhǔn)備應(yīng)用環(huán)境,包括讀取配置文件和設(shè)置環(huán)境變量
        ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        // 配置是否忽略 BeanInfo,以加快啟動(dòng)速度
        configureIgnoreBeanInfo(environment);
        // 6.打印啟動(dòng)Banner
        Banner printedBanner = printBanner(environment);
        // 7.創(chuàng)建應(yīng)用程序上下文
        context = createApplicationContext();
        // 設(shè)置應(yīng)用啟動(dòng)的上下文,用于監(jiān)控和管理啟動(dòng)過程
        context.setApplicationStartup(this.applicationStartup);
        // 8.準(zhǔn)備應(yīng)用上下文,包括加載配置、添加 Bean 等
        prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        // 9.刷新上下文,完成 Bean 的加載和依賴注入
        refreshContext(context);
        // 10.刷新后的一些操作,如事件發(fā)布等
        afterRefresh(context, applicationArguments);
        // 計(jì)算啟動(dòng)應(yīng)用程序的時(shí)間,并記錄日志
        Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
        }
        // 11.通知監(jiān)聽器應(yīng)用啟動(dòng)完成
        listeners.started(context, timeTakenToStartup);
        // 12.調(diào)用應(yīng)用程序中的 `CommandLineRunner` 或 `ApplicationRunner`,以便執(zhí)行自定義的啟動(dòng)邏輯
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        // 13.處理啟動(dòng)過程中發(fā)生的異常,并通知監(jiān)聽器
        handleRunFailure(context, ex, listeners);
        throw new IllegalStateException(ex);
    }
    try {
        // 14.計(jì)算應(yīng)用啟動(dòng)完成至準(zhǔn)備就緒的時(shí)間,并通知監(jiān)聽器
        Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
        listeners.ready(context, timeTakenToReady);
    }
    catch (Throwable ex) {
        // 處理準(zhǔn)備就緒過程中發(fā)生的異常
        handleRunFailure(context, ex, null);
        throw new IllegalStateException(ex);
    }
    // 返回已啟動(dòng)并準(zhǔn)備就緒的應(yīng)用上下文
    return context;
}

一、入口

// 1.創(chuàng)建引導(dǎo)上下文,用于管理應(yīng)用啟動(dòng)時(shí)的依賴和資源DefaultBootstrapContext bootstrapContext = createBootstrapContext();

  • bootstrapRegistryInitializers就是上一篇文章中在SpringApplication構(gòu)造方法中創(chuàng)建的引導(dǎo)注冊組件初始化器集合(查詢spring.factories文件,沒有找到BootstrapRegistryInitializer的實(shí)現(xiàn)類)
  • 調(diào)用初始化器的initialize方法,參數(shù)為bootstrapContext,也就是說每個(gè)初始化器都會(huì)對bootstrapContext進(jìn)行必要的設(shè)置和準(zhǔn)備(啟動(dòng)時(shí)需要的資源和依賴
  • 本方法是在run方法最開始調(diào)用的,也就是說引導(dǎo)注冊組件初始化器組件的執(zhí)行時(shí)機(jī)最早

  主要內(nèi)容就是實(shí)例化DefaultBootstrapContext以及遍歷BootstrapRegistryInitializer集合調(diào)用initialize,下面詳細(xì)介紹下這兩個(gè)類的作用。

// SpringApplication類屬性方法
// 引導(dǎo)注冊初始化器
private List<BootstrapRegistryInitializer> bootstrapRegistryInitializers;
private DefaultBootstrapContext createBootstrapContext() {
    // 創(chuàng)建一個(gè) DefaultBootstrapContext 實(shí)例,用于管理應(yīng)用啟動(dòng)時(shí)的資源和依賴
    DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
    // 遍歷 bootstrapRegistryInitializers 集合中的每個(gè) initializer,
    // 并調(diào)用它們的 initialize 方法,將 bootstrapContext 作為參數(shù)傳入。
    // 這一步確保每個(gè) initializer 都可以對 bootstrapContext 進(jìn)行相應(yīng)的配置,
    // 為應(yīng)用程序的啟動(dòng)過程準(zhǔn)備所需的資源。
    this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
    // 返回已完成初始化的 DefaultBootstrapContext 對象
    return bootstrapContext;
}

二、DefaultBootstrapContext

  DefaultBootstrapContext作為SpringBoot啟動(dòng)過程中的核心組件,負(fù)責(zé)環(huán)境配置、資源管理生命周期管理,確保應(yīng)用程序的順利啟動(dòng)和運(yùn)行。理解其作用有助于開發(fā)者更好地掌握SpringBoot的內(nèi)部機(jī)制。

類圖如下:

1、BootstrapRegistry接口

  一個(gè)簡單的對象注冊表,在啟動(dòng)和處理環(huán)境配置期間可用,直到ApplicationContext準(zhǔn)備好為止。提供對單例的惰性訪問,這些單例的創(chuàng)建成本可能很高,或者需要在ApplicationContext可用之前共享。

  注冊表使用Class作為鍵,這意味著只能存儲(chǔ)給定類型的單個(gè)實(shí)例。

  addCloseListener(ApplicationListener)方法可用于添加監(jiān)聽器,當(dāng)BootstrapContext關(guān)閉且ApplicationContext已準(zhǔn)備好時(shí),該監(jiān)聽器可以執(zhí)行某些操作。例如,實(shí)例可以選擇將自身注冊為常規(guī)SpringBean,以便可供應(yīng)用程序使用。

public interface BootstrapRegistry {
    // 注冊特定類型到注冊表。如果指定的類型已注冊且未以單例形式獲取,則將替換。
    <T> void register(Class<T> type, InstanceSupplier<T> instanceSupplier);
    // 如果尚未存在,則注冊特定類型到注冊表。
    <T> void registerIfAbsent(Class<T> type, InstanceSupplier<T> instanceSupplier);
    // 返回給定類型是否已經(jīng)注冊。
    <T> boolean isRegistered(Class<T> type);
    // 返回給定類型的已注冊 {@link InstanceSupplier},如果沒有則返回 null。
    <T> InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type);
    // 添加 {@link ApplicationListener},當(dāng) {@link BootstrapContext} 關(guān)閉且
    // {@link ApplicationContext} 準(zhǔn)備就緒時(shí),將調(diào)用該監(jiān)聽器,并傳遞 {@link BootstrapContextClosedEvent}。
    void addCloseListener(ApplicationListener<BootstrapContextClosedEvent> listener);
    // 提供所需時(shí)創(chuàng)建實(shí)際實(shí)例的供應(yīng)者。
    @FunctionalInterface
    interface InstanceSupplier<T> {
        // 工廠方法,在需要時(shí)創(chuàng)建實(shí)例。
        T get(BootstrapContext context);
        // 返回所提供實(shí)例的作用域。
        default Scope getScope() {
            return Scope.SINGLETON;
        }
        // 返回一個(gè)具有更新 {@link Scope} 的新 {@link InstanceSupplier}。
        default InstanceSupplier<T> withScope(Scope scope) {
            Assert.notNull(scope, "Scope must not be null");
            InstanceSupplier<T> parent = this;
            return new InstanceSupplier<T>() {
                @Override
                public T get(BootstrapContext context) {
                    return parent.get(context);
                }
                @Override
                public Scope getScope() {
                    return scope;
                }
            };
        }
        // 工廠方法,用于為給定實(shí)例創(chuàng)建 {@link InstanceSupplier}。
        static <T> InstanceSupplier<T> of(T instance) {
            return (registry) -> instance;
        }
        // 工廠方法,用于從 {@link Supplier} 創(chuàng)建 {@link InstanceSupplier}。
        static <T> InstanceSupplier<T> from(Supplier<T> supplier) {
            return (registry) -> (supplier != null) ? supplier.get() : null;
        }
    }
    // 實(shí)例的作用域。
    enum Scope {
        // 單例實(shí)例。 {@link InstanceSupplier} 將僅被調(diào)用一次,并且每次都將返回相同的實(shí)例。
        SINGLETON,
        // 原型實(shí)例。 {@link InstanceSupplier} 將在每次需要實(shí)例時(shí)調(diào)用。
        PROTOTYPE
    }
}

總結(jié):用于注冊引導(dǎo)階段的組件,在應(yīng)用啟動(dòng)時(shí)通過register方法動(dòng)態(tài)添加對象

2、BootstrapContext接口

  一個(gè)簡單的引導(dǎo)上下文,在啟動(dòng)和處理環(huán)境配置期間可用,直到ApplicationContext準(zhǔn)備好為止。提供對單例的惰性訪問,這些單例的創(chuàng)建成本可能很高,或者需要在ApplicationContext可用之前共享。

public interface BootstrapContext {
	// 如果類型已注冊,則從上下文中返回實(shí)例。如果之前未訪問過該實(shí)例,則會(huì)創(chuàng)建該實(shí)例
	<T> T get(Class<T> type) throws IllegalStateException;
	// 如果類型已注冊,則返回上下文中的實(shí)例。如果尚未訪問該實(shí)例,則將創(chuàng)建它。
    // 如果類型未注冊,則返回指定的替代實(shí)例。
	<T> T getOrElse(Class<T> type, T other);
    // 如果類型已注冊,則返回上下文中的實(shí)例。如果尚未訪問該實(shí)例,則將創(chuàng)建它。
    // 如果類型未注冊,則使用指定的供應(yīng)者提供的實(shí)例。
	<T> T getOrElseSupply(Class<T> type, Supplier<T> other);
    // 如果類型已注冊,則返回上下文中的實(shí)例。如果尚未訪問該實(shí)例,則將創(chuàng)建它。
    // 如果類型未注冊,則拋出由供應(yīng)者提供的異常。
	<T, X extends Throwable> T getOrElseThrow(Class<T> type, Supplier<? extends X> exceptionSupplier) throws X;
	// 返回給定類型是否存在注冊
	<T> boolean isRegistered(Class<T> type);
}

總結(jié):用于提供對引導(dǎo)階段注冊組件的只讀訪問,一旦BootstrapRegistry注冊完成并構(gòu)建成BootstrapContext,所有組件可以通過get方法被安全地訪問,直到應(yīng)用啟動(dòng)完成。

3、DefaultBootstrapContext實(shí)現(xiàn)類

ConfigurableBootstrapContext是一個(gè)空接口,所以直接看核心內(nèi)容DefaultBootstrapContext

public interface ConfigurableBootstrapContext extends BootstrapRegistry, BootstrapContext {
}

  DefaultBootstrapContext是一個(gè)實(shí)現(xiàn)了ConfigurableBootstrapContext接口的類,主要用于管理應(yīng)用啟動(dòng)過程中的實(shí)例供應(yīng)者實(shí)例,提供了注冊、獲取、關(guān)閉監(jiān)聽等功能。以下是主要功能的總結(jié):

1.實(shí)例供應(yīng)者管理:

  • 使用Map<Class<?>, InstanceSupplier<?>> instanceSuppliers來存儲(chǔ)類型到實(shí)例供應(yīng)者的映射,可以通過registerregisterIfAbsent方法來注冊實(shí)例供應(yīng)者
  • register方法支持覆蓋現(xiàn)有的實(shí)例供應(yīng)者,而registerIfAbsent則僅在類型未注冊的情況下注冊實(shí)例供應(yīng)者

2.實(shí)例管理:

  • 使用Map<Class<?>, Object> instances存儲(chǔ)已創(chuàng)建的實(shí)例
  • 提供getgetOrElse、getOrElseSupply等方法來獲取實(shí)例。如果實(shí)例尚未創(chuàng)建,則調(diào)用相應(yīng)的實(shí)例供應(yīng)者來創(chuàng)建實(shí)例,并在單例作用域下將其存儲(chǔ)

3.事件管理(后面文章調(diào)用時(shí)候細(xì)講):

  • 使用ApplicationEventMulticaster來管理事件的發(fā)布和監(jiān)聽
  • 提供addCloseListener方法添加關(guān)閉監(jiān)聽器,并在close方法中發(fā)布BootstrapContextClosedEvent事件
public class DefaultBootstrapContext implements ConfigurableBootstrapContext {
	// 存儲(chǔ)實(shí)例供應(yīng)者的映射
	private final Map<Class<?>, InstanceSupplier<?>> instanceSuppliers = new HashMap<>();
	// 存儲(chǔ)已創(chuàng)建實(shí)例的映射
	private final Map<Class<?>, Object> instances = new HashMap<>();
	// 事件廣播器,用于發(fā)布應(yīng)用事件
	private final ApplicationEventMulticaster events = new SimpleApplicationEventMulticaster();
	@Override
	public <T> void register(Class<T> type, InstanceSupplier<T> instanceSupplier) {
		// 注冊特定類型的實(shí)例供應(yīng)者
		register(type, instanceSupplier, true);
	}
	@Override
	public <T> void registerIfAbsent(Class<T> type, InstanceSupplier<T> instanceSupplier) {
		// 如果尚未注冊,則注冊特定類型的實(shí)例供應(yīng)者
		register(type, instanceSupplier, false);
	}
	private <T> void register(Class<T> type, InstanceSupplier<T> instanceSupplier, boolean replaceExisting) {
		// 檢查類型和實(shí)例供應(yīng)者是否為空
		Assert.notNull(type, "Type must not be null");
		Assert.notNull(instanceSupplier, "InstanceSupplier must not be null");
		synchronized (this.instanceSuppliers) {
			// 檢查類型是否已注冊
			boolean alreadyRegistered = this.instanceSuppliers.containsKey(type);
			if (replaceExisting || !alreadyRegistered) {
				// 確保實(shí)例尚未創(chuàng)建
				Assert.state(!this.instances.containsKey(type), () -> type.getName() + " has already been created");
				// 注冊實(shí)例供應(yīng)者
				this.instanceSuppliers.put(type, instanceSupplier);
			}
		}
	}
	@Override
	public <T> boolean isRegistered(Class<T> type) {
		// 檢查給定類型是否已注冊
		synchronized (this.instanceSuppliers) {
			return this.instanceSuppliers.containsKey(type);
		}
	}
	@Override
	@SuppressWarnings("unchecked")
	public <T> InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type) {
		// 返回已注冊的實(shí)例供應(yīng)者
		synchronized (this.instanceSuppliers) {
			return (InstanceSupplier<T>) this.instanceSuppliers.get(type);
		}
	}
	@Override
	public <T> T get(Class<T> type) throws IllegalStateException {
		// 獲取指定類型的實(shí)例,如果未注冊則拋出異常
		return getOrElseThrow(type, () -> new IllegalStateException(type.getName() + " has not been registered"));
	}
	@Override
	public <T> T getOrElse(Class<T> type, T other) {
		// 獲取指定類型的實(shí)例,如果未注冊則返回其他提供的實(shí)例
		return getOrElseSupply(type, () -> other);
	}
	@Override
	public <T> T getOrElseSupply(Class<T> type, Supplier<T> other) {
		// 嘗試獲取指定類型的實(shí)例,如果未注冊則調(diào)用其他供應(yīng)者
		synchronized (this.instanceSuppliers) {
			InstanceSupplier<?> instanceSupplier = this.instanceSuppliers.get(type);
			return (instanceSupplier != null) ? getInstance(type, instanceSupplier) : other.get();
		}
	}
	@Override
	public <T, X extends Throwable> T getOrElseThrow(Class<T> type, Supplier<? extends X> exceptionSupplier) throws X {
		// 嘗試獲取指定類型的實(shí)例,如果未注冊則拋出由供應(yīng)者提供的異常
		synchronized (this.instanceSuppliers) {
			InstanceSupplier<?> instanceSupplier = this.instanceSuppliers.get(type);
			if (instanceSupplier == null) {
				throw exceptionSupplier.get();
			}
			return getInstance(type, instanceSupplier);
		}
	}
	@SuppressWarnings("unchecked")
	private <T> T getInstance(Class<T> type, InstanceSupplier<?> instanceSupplier) {
		// 獲取實(shí)例,如果尚未創(chuàng)建則調(diào)用實(shí)例供應(yīng)者
		T instance = (T) this.instances.get(type);
		if (instance == null) {
			instance = (T) instanceSupplier.get(this);
			// 如果作用域?yàn)閱卫?,則存儲(chǔ)該實(shí)例
			if (instanceSupplier.getScope() == Scope.SINGLETON) {
				this.instances.put(type, instance);
			}
		}
		return instance;
	}
	@Override
	public void addCloseListener(ApplicationListener<BootstrapContextClosedEvent> listener) {
		// 添加關(guān)閉監(jiān)聽器,當(dāng) BootstrapContext 關(guān)閉時(shí)觸發(fā)
		this.events.addApplicationListener(listener);
	}
	/**
	 * 當(dāng) {@link BootstrapContext} 關(guān)閉且 {@link ApplicationContext} 已準(zhǔn)備好時(shí)調(diào)用的方法。
	 * @param applicationContext 已準(zhǔn)備好的上下文
	 */
	public void close(ConfigurableApplicationContext applicationContext) {
		// 發(fā)布 BootstrapContext 關(guān)閉事件
		this.events.multicastEvent(new BootstrapContextClosedEvent(this, applicationContext));
	}
}

三、BootstrapRegistryInitializer

1、作用及觸發(fā)時(shí)機(jī)

  • 回調(diào)接口,用于在BootstrapRegistry(對象注冊表)使用之前進(jìn)行初始化
  • 作用:應(yīng)用程序啟動(dòng)的早期階段進(jìn)行必要的初始化配置
@FunctionalInterface
public interface BootstrapRegistryInitializer {
    // 此方法在應(yīng)用啟動(dòng)過程中被調(diào)用,允許實(shí)現(xiàn)者向注冊表注冊必要的組件或服務(wù)。
    // 注冊的組件隨后可以在應(yīng)用上下文中訪問。實(shí)現(xiàn)者應(yīng)僅注冊應(yīng)用所需的類型。
    void initialize(BootstrapRegistry registry);
}

  引導(dǎo)注冊組件初始化器BootstrapRegistryInitializer在SpringApplication的構(gòu)造方法中通過查找META-INF/spring.factories文件進(jìn)行加載,然后在引導(dǎo)上下文實(shí)例創(chuàng)建完成后,遍歷并調(diào)用所有BootstrapRegistryInitializer#initialize方法。

普通SpringBoot項(xiàng)目沒有其實(shí)現(xiàn),找了個(gè)SpringCloud項(xiàng)目看了下,有兩個(gè)

2、示例

自定義BootstrapRegistryInitializer

public class MyBootstrapRegistryInitializer implements BootstrapRegistryInitializer {
    @Override
    public void initialize(BootstrapRegistry registry) {
        // 注冊一個(gè)自定義服務(wù)
        registry.register(MyCustomService.class, context -> new MyCustomService());
        System.out.println("MyBootstrapRegistryInitializer已注冊");
    }
}
class MyCustomService {
}

META-INF/spring.factories文件中添加對自定義初始化器的配置

org.springframework.boot.BootstrapRegistryInitializer=com.xc.config.MyBootstrapRegistryInitializer

啟動(dòng)服務(wù)

ps:BootstrapRegistryInitializer是SpringBoot第一個(gè)擴(kuò)展點(diǎn)(注冊組件)

總結(jié)

  • 引導(dǎo)上下文DefaultBootstrapContext創(chuàng)建:在run方法的最初階段被實(shí)例化,并通過BootstrapRegistryInitializer(第一個(gè)注冊組件擴(kuò)展點(diǎn))進(jìn)行必要的初始化,確保應(yīng)用啟動(dòng)時(shí)所需的資源和依賴得到妥善管理
  • BootstrapRegistry的作用:該接口作為對象注冊表,允許在應(yīng)用啟動(dòng)早期階段進(jìn)行組件的注冊和管理,提供了對高成本實(shí)例的惰性訪問
  • BootstrapContext的角色:作為引導(dǎo)上下文的只讀訪問接口,它確保注冊的組件能夠安全、可靠地在應(yīng)用上下文準(zhǔn)備好之前被訪問

到此這篇關(guān)于SpringBoot啟動(dòng)流程之引導(dǎo)上下文DefaultBootstrapContext的過程的文章就介紹到這了,更多相關(guān)SpringBoot引導(dǎo)上下文DefaultBootstrapContext內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java線程安全中的單例模式

    Java線程安全中的單例模式

    這篇文章主要介紹了Java線程安全中的單例模式,需要的朋友可以參考下
    2015-02-02
  • Java構(gòu)建高效結(jié)果緩存方法示例

    Java構(gòu)建高效結(jié)果緩存方法示例

    這篇文章主要介紹了Java構(gòu)建高效結(jié)果緩存方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 超詳細(xì)的Java 問題排查工具單

    超詳細(xì)的Java 問題排查工具單

    這篇文章主要介紹了超詳細(xì)的Java 問題排查工具單,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • 簡單幾步實(shí)現(xiàn)將Spring security4.x升級到5.x

    簡單幾步實(shí)現(xiàn)將Spring security4.x升級到5.x

    這篇文章主要介紹了簡單幾步實(shí)現(xiàn)將Spring security4.x升級到5.x方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 深入研究spring boot集成kafka之spring-kafka底層原理

    深入研究spring boot集成kafka之spring-kafka底層原理

    這篇文章主要深入研究了spring boot集成kafka如何實(shí)現(xiàn)spring-kafka的底層原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-02-02
  • springIOC的使用流程及spring中使用類型轉(zhuǎn)換器的方式

    springIOC的使用流程及spring中使用類型轉(zhuǎn)換器的方式

    Spring IOC是Spring框架的核心原理之一,它是一種軟件設(shè)計(jì)模式,用于管理應(yīng)用程序中的對象依賴關(guān)系,這篇文章主要介紹了springIOC的使用流程以及spring中如何使用類型轉(zhuǎn)換器,需要的朋友可以參考下
    2023-06-06
  • 淺談cookie 和session 的區(qū)別

    淺談cookie 和session 的區(qū)別

    下面小編就為大家?guī)硪黄獪\談cookie 和session 的區(qū)別。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-06-06
  • MapReduce實(shí)現(xiàn)TopN效果示例解析

    MapReduce實(shí)現(xiàn)TopN效果示例解析

    這篇文章主要為大家介紹了MapReduce實(shí)現(xiàn)TopN效果示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • java傳入時(shí)間戳返回LocalDateTime的實(shí)現(xiàn)方法

    java傳入時(shí)間戳返回LocalDateTime的實(shí)現(xiàn)方法

    這篇文章主要介紹了java傳入時(shí)間戳返回LocalDateTime的實(shí)現(xiàn)方法,在Java中將時(shí)間戳轉(zhuǎn)換為LocalDateTime時(shí)需要注意時(shí)區(qū)問題,因?yàn)長ocalDateTime不包含時(shí)區(qū)信息,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-11-11
  • Java I/O流實(shí)例之簡歷替換

    Java I/O流實(shí)例之簡歷替換

    流是一種抽象概念,它代表了數(shù)據(jù)的無結(jié)構(gòu)化傳遞。。用來進(jìn)行輸入輸出操作的流就稱為IO流。換句話說,IO流就是以流的方式進(jìn)行輸入輸出
    2021-09-09

最新評論