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

面試常問之如何理解Spring當中的Bean

 更新時間:2026年05月06日 08:59:51   作者:SamDeepThinking  
在Spring框架中Bean是被IOC?容器管理的對象,是?Spring應(yīng)用的核心組成部分,所有由Spring容器創(chuàng)建、裝配和管理的對象都稱為Bean,這篇文章主要介紹了面試常問之如何理解Spring當中Bean的相關(guān)資料,需要的朋友可以參考下

面試里經(jīng)常被問到一個問題:什么是Spring Bean?

工作三五年的開發(fā)者,大部分人的回答是「被Spring管理的對象」。這個回答不算錯,但信息量約等于零。所有關(guān)鍵的東西都藏在「管理」這兩個字里。管理了什么?怎么管理的?為什么需要管理?追問一層就接不住了。

問題出在哪里?這個定義是用Spring來解釋Bean,沒有跳出框架去理解它。你記住了一個說法,但追問一層你會發(fā)現(xiàn)自己說不清楚。

要搞清楚Bean到底是什么,得先把Spring放到一邊,回到一個更根本的問題:在沒有Spring的時候,我們是怎么寫代碼的,遇到了什么麻煩。

想象一個典型的訂單系統(tǒng),三層架構(gòu):OrderController處理請求,OrderService處理業(yè)務(wù)邏輯,OrderRepository和UserRepository負責(zé)數(shù)據(jù)庫操作,底層共用一個DataSource。沒有任何框架,全靠手動組裝,啟動代碼大概長這樣:

public class Application {
    public static void main(String[] args) {
        // 創(chuàng)建數(shù)據(jù)源
        DataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/demo");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");

        // 創(chuàng)建數(shù)據(jù)訪問層
        OrderRepository orderRepository = new OrderRepository(dataSource);
        UserRepository userRepository = new UserRepository(dataSource);

        // 創(chuàng)建業(yè)務(wù)層
        OrderService orderService = new OrderService(orderRepository, userRepository);

        // 創(chuàng)建控制層
        OrderController orderController = new OrderController(orderService);

        // 啟動服務(wù)器,把controller注冊進去...
    }
}

這段代碼功能上完全沒問題,小項目跑得很穩(wěn)。問題出在規(guī)模增長之后?,F(xiàn)在只有4個對象,手動組裝還看得清楚。一個真實的Spring Boot項目里,幾十上百個Service、Repository、Controller、各種配置類、中間件客戶端,它們之間的依賴關(guān)系是一張網(wǎng)。OrderService依賴OrderRepository和UserRepository,PaymentService依賴OrderService和PaymentGateway,NotificationService依賴UserRepository和EmailClient……每加一個新類,你都得回到這個啟動代碼里,搞清楚它依賴誰、誰依賴它,然后手動把依賴關(guān)系對接好。改一個類的構(gòu)造器簽名,所有創(chuàng)建它的地方都要跟著改。

很多人以為Spring的價值是「省了幾行new的代碼」。不是。手動new十幾個對象不費事。費事的是幾百個對象之間的依賴關(guān)系全靠你自己理清楚,每一次變動都可能牽連好幾處。真正的痛點不是對象的創(chuàng)建,而是對象之間依賴關(guān)系的管理。

面對這個問題,解決的思路可以是這樣子:搞一個統(tǒng)一的地方,專門負責(zé)創(chuàng)建所有對象、管理它們之間的依賴關(guān)系。你只需要告訴這個地方「我有哪些類、它們各自需要什么」,剩下的創(chuàng)建和組裝工作全交給它。

這個思路就是容器的雛形。Spring容器干的事:你告訴我有哪些類需要管理,我來負責(zé)創(chuàng)建它們、把它們之間的依賴關(guān)系接好、在合適的時機銷毀它們。

光說概念太抽象,不如自己寫一個最簡版本的容器,看看它的核心到底是什么。下面這段代碼大概50行,能注冊類、創(chuàng)建對象、自動注入依賴:

public class SimpleContainer {

    // 存儲注冊信息:Bean名字 → 類的Class對象
    private Map<String, Class<?>> registry = new HashMap<>();

    // 存儲已經(jīng)創(chuàng)建好的單例對象
    private Map<String, Object> singletonCache = new HashMap<>();

    // 注冊一個類,告訴容器需要管理它
    public void register(String name, Class<?> clazz) {
        registry.put(name, clazz);
    }

    // 獲取Bean:先查緩存,沒有就創(chuàng)建
    public Object getBean(String name) {
        // 先查單例緩存,有就直接返回
        if (singletonCache.containsKey(name)) {
            return singletonCache.get(name);
        }

        Class<?> clazz = registry.get(name);
        if (clazz == null) {
            throw new RuntimeException("沒有找到名為 " + name + " 的Bean定義");
        }

        try {
            // 通過反射創(chuàng)建對象
            Object instance = clazz.getDeclaredConstructor().newInstance();

            // 掃描這個對象的所有字段,嘗試自動注入依賴
            for (Field field : clazz.getDeclaredFields()) {
                // 在registry里找類型匹配的Bean
                for (Map.Entry<String, Class<?>> entry : registry.entrySet()) {
                    if (field.getType().isAssignableFrom(entry.getValue())) {
                        field.setAccessible(true);
                        // 遞歸獲取依賴的Bean(觸發(fā)依賴的創(chuàng)建和注入)
                        field.set(instance, getBean(entry.getKey()));
                    }
                }
            }

            // 放入單例緩存
            singletonCache.put(name, instance);
            return instance;
        } catch (Exception e) {
            throw new RuntimeException("創(chuàng)建Bean失敗: " + name, e);
        }
    }
}

用起來是這樣的:

SimpleContainer container = new SimpleContainer();

// 告訴容器有哪些類
container.register("dataSource", HikariDataSource.class);
container.register("orderRepository", OrderRepository.class);
container.register("userRepository", UserRepository.class);
container.register("orderService", OrderService.class);
container.register("orderController", OrderController.class);

// 直接從容器拿,依賴自動接好了
OrderController controller = (OrderController) container.getBean("orderController");

對比之前手動組裝的代碼,變化在哪?你不再關(guān)心「誰該傳給誰」這件事了。你只管告訴容器有哪些類,容器自己分析它們的字段類型,去registry里找匹配的Bean,遞歸地完成整條依賴鏈的創(chuàng)建和注入。

這段代碼雖然粗糙,但它揭示了Spring容器最核心的骨架:一個Map存「有哪些東西需要管理」,另一個Map存「已經(jīng)創(chuàng)建好的成品」。 所有Spring容器的復(fù)雜性,生命周期回調(diào)、作用域管理、循環(huán)依賴處理、AOP代理,都是在這個骨架上疊加的特性。骨架沒變過,只是功能越來越豐富。

有人會說,這也太簡化了吧?Spring的真實實現(xiàn)比這復(fù)雜得多。確實。這個簡化版忽略了很多東西:構(gòu)造器參數(shù)怎么選擇、同一個類型有多個Bean怎么辦、延遲加載怎么處理、循環(huán)依賴怎么解決。這些都是工程實踐中必須面對的問題。

但理解一個框架,要先把骨架看清楚,再去看長在骨架上的血肉。

你知道了核心是兩個Map,后面接觸到每一個高級特性,都能定位到它是在修改哪個Map、在哪個環(huán)節(jié)介入。

上面的簡化容器有一個明顯的不足:registry里只存了一個Class對象。也就是說,容器只知道「創(chuàng)建什么」,但不知道很多其他信息。實際場景中,一個對象被容器管理,容器需要知道更多的事情:

  • 這個對象是整個應(yīng)用只要一份(單例),還是每次請求都新建一份?
  • 它需不需要延遲創(chuàng)建(應(yīng)用啟動時不創(chuàng)建,等真正用到時再創(chuàng)建)?
  • 它依賴其他哪些Bean,這些Bean必須先創(chuàng)建好?
  • 創(chuàng)建完成后,有沒有什么初始化動作要執(zhí)行(比如連接池要預(yù)熱、緩存要加載)?
  • 應(yīng)用關(guān)閉時,有沒有什么清理動作要做(比如關(guān)閉連接池、釋放文件句柄)?
  • 同一個類型有多個Bean時,哪個是默認優(yōu)先使用的?

這些信息需要一個結(jié)構(gòu)化的地方來存儲。在Spring里,這個結(jié)構(gòu)叫Bean定義,你可以理解成一份「制造說明書」。用代碼來表達,大概是這樣的結(jié)構(gòu):

public class BeanDefinition {

    // 這個Bean對應(yīng)的類
    private Class<?> beanClass;

    // 作用域:singleton表示全局一份,prototype表示每次新建
    private String scope = "singleton";

    // 是否延遲初始化
    private boolean lazyInit = false;

    // 依賴的其他Bean名字,這些Bean必須在它之前創(chuàng)建
    private String[] dependsOn;

    // 初始化時要調(diào)用的方法名
    private String initMethodName;

    // 銷毀時要調(diào)用的方法名
    private String destroyMethodName;

    // 同類型多個Bean時,是否優(yōu)先使用這個
    private boolean primary = false;
}

有了這個視角,Bean和普通Java對象的區(qū)別就清晰了。你在代碼里寫new OrderService(),JVM只是調(diào)一下構(gòu)造器,創(chuàng)建一個對象放在堆上,別的什么都不管。而容器管理的Bean,背后有一份完整的制造說明書,容器知道它什么時候創(chuàng)建、怎么創(chuàng)建、創(chuàng)建之后做什么、銷毀之前做什么。Bean = 對象 + 制造說明書 + 容器的全程托管。 三樣?xùn)|西少了任何一個,都不叫Bean。

容器有了說明書,創(chuàng)建一個Bean的過程也就不是簡單地調(diào)一下構(gòu)造器了。它有一整套標準化的流程。這里不展開每一步的實現(xiàn)細節(jié),只畫一條時間線,先有個整體印象:

用一個不太嚴格但方便理解的類比:

這個過程像裝修一套房子。買到毛坯房是實例化,這時候房子有了,但什么都沒有。接水電氣是屬性填充,把它需要的各種依賴(水、電、網(wǎng)絡(luò))接進來。驗收檢查是初始化回調(diào),確認一切就緒,做最后的調(diào)試和測試。然后是入住使用。最后是拆遷,清理所有資源,把占用的東西歸還。

生命周期不是框架在故弄玄虛。一個對象從創(chuàng)建到真正可用之間,確實有很多事情要做。DataSource需要初始化連接池,緩存需要預(yù)熱,消息監(jiān)聽器需要注冊到消息隊列。這些不是構(gòu)造器能一步搞定的。容器把這些步驟標準化,每個步驟還留了擴展點,讓你在特定階段插入自己的邏輯。

回到一個更實際的問題:你怎么告訴Spring,你的哪些類需要被當成Bean來管理?

最常見的方式是在類上面加注解。Spring提供了四個用來標記Bean的注解:@Component、@Service、@Repository、@Controller。很多教程告訴你,Service層用@Service,Controller層用@Controller,DAO層用@Repository。但很少有人解釋為什么。

這四個注解之間的關(guān)系,簡單說就是:@Service、@Repository、@Controller都是@Component的「派生版」。它們的定義方式類似這樣:

// @Service的定義上面標注了@Component
@Component
public @interface Service {
    String value() default "";
}

// @Repository的定義上面標注了@Component
@Component
public @interface Repository {
    String value() default "";
}

// @Controller的定義上面標注了@Component
@Component
public @interface Controller {
    String value() default "";
}

Spring在掃描包路徑的時候,查找的是帶有@Component注解的類。因為@Service、@Repository、@Controller上面都標注了@Component,所以它們也會被掃描到。從「把一個類注冊成Bean」這件事來看,這四個注解完全等價。你把所有@Service換成@Component,項目一樣能正常跑。

那為什么不全用@Component?

從兩個角度看。一是語義表達。其他開發(fā)者看到@Repository就知道這是數(shù)據(jù)訪問層,看到@Service就知道這是業(yè)務(wù)層。注解在這里承擔(dān)了代碼文檔的角色。在三五個人的小團隊里,這點區(qū)別可能感受不明顯。幾十人的項目里,注解的語義信號對代碼理解效率的影響比想象中大得多。

二是框架層面的區(qū)別對待。雖然注冊Bean時這四個注解等價,但Spring在后續(xù)處理中會對特定注解做額外的事情。@Repository標記的類,Spring會給它加一層異常轉(zhuǎn)譯,把數(shù)據(jù)訪問層拋出的底層異常(比如JDBC的SQLException)自動包裝成Spring統(tǒng)一的數(shù)據(jù)訪問異常體系。@Controller標記的類,Spring MVC會把它識別為請求處理器,掃描里面的@RequestMapping方法來建立請求映射。這些特殊處理不在Bean注冊階段,而是在各自模塊的后處理階段。

@Component系列注解適用于你自己寫的類。遇到第三方庫的類,比如你想把一個RestTemplate注冊成Bean,沒法去改RestTemplate的源碼加@Component。這時候用@Bean注解,在一個配置類里寫一個方法,方法返回值就是你要注冊的Bean:

@Configuration
public class AppConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@Component是標記一個類讓Spring自動掃描并注冊,@Bean是在方法上手動告訴Spring怎么創(chuàng)建一個對象。兩種方式的終點相同:往容器的注冊表里寫入一條Bean定義。

這里有一個容易忽略的細節(jié):上面這個配置類用的是@Configuration,不是@Component。雖然@Configuration本身也是@Component的派生注解(也會被掃描為Bean),但它有一個@Component不具備的特殊行為。

看這個場景:

@Configuration
public class AppConfig {

    @Bean
    public DataSource dataSource() {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:mysql://localhost:3306/demo");
        ds.setUsername("root");
        ds.setPassword("123456");
        return ds;
    }

    @Bean
    public OrderRepository orderRepository() {
        // 注意:這里調(diào)用了dataSource()方法
        return new OrderRepository(dataSource());
    }

    @Bean
    public UserRepository userRepository() {
        // 這里也調(diào)用了dataSource()方法
        return new UserRepository(dataSource());
    }
}

orderRepository()和userRepository()各調(diào)用了一次dataSource()。如果這是普通的Java方法調(diào)用,兩次調(diào)用會執(zhí)行兩次new HikariDataSource(),創(chuàng)建出兩個不同的數(shù)據(jù)源對象。兩個Repository各持有一個獨立的連接池,這顯然不是你想要的。

實際運行時,兩個Repository拿到的是同一個DataSource實例。原因是Spring在啟動時給@Configuration類生成了一個動態(tài)子類(通過CGLIB字節(jié)碼技術(shù))。這個子類覆蓋了所有@Bean方法的執(zhí)行邏輯:當你在方法內(nèi)部調(diào)用dataSource()時,執(zhí)行的不是原始的new邏輯,而是先去容器的單例緩存里查。如果dataSource這個Bean已經(jīng)創(chuàng)建過了,直接返回緩存里的實例。

我以前一直覺得@Configuration和@Component沒什么本質(zhì)區(qū)別,直到在一個項目里踩了坑。排查一個連接池告警,發(fā)現(xiàn)數(shù)據(jù)庫連接數(shù)莫名其妙翻倍了。查到最后,是有人把一個配置類的@Configuration改成了@Component(可能是覺得既然都能注冊Bean,用哪個都一樣)。改完之后,兩個Repository各自持有了一個獨立的DataSource,連接池被創(chuàng)建了兩份。這才意識到@Configuration的CGLIB代理在保證@Bean方法的單例語義上是不可少的。

有一個相關(guān)的優(yōu)化值得提一下:如果你的@Configuration類里的@Bean方法之間沒有互相調(diào)用的情況,可以用@Configuration(proxyBeanMethods = false)主動關(guān)掉CGLIB代理。Spring Boot的很多自動配置類就是這么做的,能加快應(yīng)用啟動速度。這是一個知道原理之后才能做出的優(yōu)化判斷。

容器創(chuàng)建好了Bean,接下來的問題是怎么把它們之間的依賴關(guān)系接好。這就是依賴注入。日常開發(fā)中最常用的兩個注入注解是@Autowired和@Resource,它們的核心行為差異用一句話就能說清:@Autowired按類型找,@Resource按名字找。

@Autowired的匹配邏輯是:先按字段的類型去容器里查,如果只找到一個,直接注入。如果同一個類型有多個Bean,再看字段名是否和某個Bean的名字匹配。@Resource正好反過來,默認按字段名去容器里查Bean名字,名字匹配不上再按類型找。

實際項目里選哪個?團隊保持一致就好。Spring官方現(xiàn)在更推薦構(gòu)造器注入,連@Autowired注解都可以不寫。當一個類只有一個構(gòu)造器時,Spring會自動把構(gòu)造器參數(shù)從容器中注入:

構(gòu)造器注入有一個好處:依賴字段可以聲明為final,對象創(chuàng)建之后依賴關(guān)系不可變。字段注入做不到這一點。

日常開發(fā)中的Bean

講了這么多原理,回到一個實際的問題:你每天寫的代碼里,哪些東西是Bean?

下面這張表覆蓋了一個典型Spring Boot項目中常見的Bean來源:

分類典型代表誰注冊的你需要做什么
你自己寫的業(yè)務(wù)類XxxService、XxxController、XxxRepository你加@Component系列注解在類上標注注解
你手動配置的BeanRestTemplate、ObjectMapper、線程池、攔截器你在@Configuration里寫@Bean方法寫配置類和@Bean方法
Spring Boot自動配置的DataSource、JdbcTemplate、RedisTemplate、事務(wù)管理器spring-boot-autoconfigure里的自動配置類引入對應(yīng)的starter依賴即可,不需要寫任何代碼
Spring MVC基礎(chǔ)設(shè)施DispatcherServlet、HandlerMapping、參數(shù)解析器Spring MVC自動注冊引入spring-boot-starter-web
AOP相關(guān)你寫的@Aspect類、各種通知Spring AOP框架加@Aspect和切點表達式
事件機制ApplicationEventPublisher、你寫的@EventListener方法所在的類Spring容器實現(xiàn)接口或加注解
你以為不是Bean但其實是的@Configuration類本身、@Aspect類本身Spring自動識別并注冊通常不需要額外感知

一個容易產(chǎn)生誤區(qū)的地方:不是所有Java對象都應(yīng)該注冊成Bean。Entity、DTO、VO這些數(shù)據(jù)傳輸對象不該是Bean。它們的生命周期跟隨請求或業(yè)務(wù)流程,每次請求可能產(chǎn)生不同的實例,這和容器管理單例的模式是沖突的。工具類如果全是靜態(tài)方法,也不需要注冊成Bean。

判斷標準就兩條:這個對象需不需要被別的Bean依賴注入?需不需要容器管理它的生命周期(初始化、銷毀)?兩個答案都是否,它不該是Bean。

下面這張對比表可以幫你快速區(qū)分Bean和普通對象:

維度Spring Bean普通Java對象
創(chuàng)建方式容器根據(jù)Bean定義創(chuàng)建代碼里直接new
生命周期容器全程托管(創(chuàng)建→注入→初始化→使用→銷毀)創(chuàng)建者管理,GC回收
依賴注入容器自動完成手動通過構(gòu)造器或setter傳參
默認實例數(shù)單例(整個應(yīng)用一份)每次new都是新對象
AOP支持可以被代理增強(事務(wù)、日志、權(quán)限等)不支持
能否被其他Bean依賴可以,容器知道它的存在不行,容器感知不到
典型代表Service、Controller、Repository、配置類、中間件客戶端Entity、DTO、VO、工具類

小結(jié)

回到開頭那個面試問題。讀到這里,對Bean的認知應(yīng)該不再停留在「被Spring管理的對象」這個層面了。容器的核心是兩個Map:一個存制造說明書,一個存創(chuàng)建好的成品。Bean是容器基于說明書創(chuàng)建、組裝依賴、管理全生命周期的對象。你用@Component告訴容器哪些類需要管理,用@Bean告訴容器怎么創(chuàng)建第三方類的實例,容器負責(zé)剩下的一切。

做了十幾年項目,我覺得理解Bean這個概念有一個容易走偏的方向:過度關(guān)注容器的內(nèi)部實現(xiàn)細節(jié),去追每一行源碼的執(zhí)行路徑,反而忘了停下來想一想「什么該交給容器管理、什么不該」。項目里見過不少把DTO、值對象甚至臨時變量都注冊成Bean的代碼,容器里塞了一堆不需要被管理的東西,代碼反而更難讀了。Bean的設(shè)計初衷是讓你專注于業(yè)務(wù)邏輯,把對象的創(chuàng)建和組裝交給框架。如果一個對象被注冊成Bean之后,代碼沒有因此變得更簡單,那它可能不該是Bean。

到此這篇關(guān)于面試常問之如何理解Spring當中Bean的文章就介紹到這了,更多相關(guān)Spring中Bean理解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java:抽象類與模板方法模式詳解

    java:抽象類與模板方法模式詳解

    這篇文章主要介紹了Java抽象類的構(gòu)造模板模式用法,結(jié)合實例形式分析了java使用抽象類構(gòu)造模板模式相關(guān)操作技巧,需要的朋友可以參考下
    2021-09-09
  • Java中的LinkedHashMap源碼詳解

    Java中的LinkedHashMap源碼詳解

    這篇文章主要介紹了Java中的LinkedHashMap源碼詳解,LinkedHashMap的實現(xiàn)方式是將所有的Entry節(jié)點鏈入一個雙向鏈表,并且它的底層數(shù)據(jù)結(jié)構(gòu)是HashMap,因此,LinkedHashMap具有HashMap的所有特性,但在存取元素的細節(jié)實現(xiàn)上有所不同,需要的朋友可以參考下
    2023-09-09
  • java遞歸實現(xiàn)科赫雪花

    java遞歸實現(xiàn)科赫雪花

    這篇文章主要為大家詳細介紹了java遞歸實現(xiàn)科赫雪花,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • Java將Date日期類型字段轉(zhuǎn)換成json字符串的方法

    Java將Date日期類型字段轉(zhuǎn)換成json字符串的方法

    這篇文章主要給大家介紹了關(guān)于Java將Date日期類型字段轉(zhuǎn)換成json字符串的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Elasticsearch倒排索引詳解及實際應(yīng)用中的優(yōu)化

    Elasticsearch倒排索引詳解及實際應(yīng)用中的優(yōu)化

    Elasticsearch(ES)使用倒排索引來加速文本的搜索速度,倒排索引之所以高效,主要是因為它改變了數(shù)據(jù)的組織方式,使得查詢操作可以快速完成,這篇文章主要給大家介紹了關(guān)于Elasticsearch倒排索引詳解及實際應(yīng)用中優(yōu)化的相關(guān)資料,需要的朋友可以參考下
    2024-08-08
  • SpringBoot使用PageHelper插件實現(xiàn)Mybatis分頁效果

    SpringBoot使用PageHelper插件實現(xiàn)Mybatis分頁效果

    這篇文章主要介紹了SpringBoot使用PageHelper插件實現(xiàn)Mybatis分頁效果,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作有一定的參考借鑒價值,需要的朋友可以參考下
    2024-02-02
  • Java RabbitMQ高級特性詳細分析

    Java RabbitMQ高級特性詳細分析

    為了保證消息的可靠性傳輸,包括投遞消息的生產(chǎn)方能投遞成功,和消息消費的消費方正確消費,RabbitMQ 提供了兩個確認機制,由于消息按照流通的順序從左到右,因此為保證可靠性,MQ必須對 Producer進行確認,Consumer 必須對 MQ 進行確認
    2022-08-08
  • 基于SpringBoot + 七牛云 + Quartz實現(xiàn)圖片存儲與定時清理

    基于SpringBoot + 七牛云 + Quartz實現(xiàn)圖片存儲與定時清理

    這篇文章主要介紹了在實際項目中使用七牛云對象存儲進行圖片存儲的方法,以及如何實現(xiàn)套餐管理(包括圖片上傳和多對多關(guān)聯(lián)檢查組)的前端和后端功能,此外,還詳細講解了如何使用Quartz定時任務(wù)組件自動清理垃圾圖片,以節(jié)省存儲資源,需要的朋友可以參考下
    2026-04-04
  • SpringBoot集成極光推送的實現(xiàn)代碼

    SpringBoot集成極光推送的實現(xiàn)代碼

    工作中經(jīng)常會遇到服務(wù)器向App推送消息的需求,一般企業(yè)中選擇用極光推送的比較多,本文就介紹了SpringBoot集成極光推送的實現(xiàn)代碼,感興趣的可以了解一下
    2023-08-08
  • Java Ribbon負載均衡詳細講解

    Java Ribbon負載均衡詳細講解

    Ribbon其實就是一個軟負載均衡的客戶端組件,他可以和其他所需請求的客戶端結(jié)合使用,這篇文章主要介紹了Ribbon負載均衡服務(wù)調(diào)用案例代碼,需要的朋友可以參考下
    2023-01-01

最新評論

黔西县| 旬邑县| 溧水县| 全椒县| 屏东市| 苗栗市| 山阴县| 中阳县| 株洲市| 疏附县| 祁门县| 德钦县| 新津县| 东海县| 班戈县| 天全县| 夹江县| 武宣县| 齐河县| 湘阴县| 金昌市| 朝阳区| 凉山| 额尔古纳市| 太和县| 吉安市| 二连浩特市| 汉寿县| 五莲县| 屯留县| 晴隆县| 常熟市| 本溪| 遵义县| 隆化县| 遵化市| 班玛县| 丹寨县| 中阳县| 双鸭山市| 奇台县|