Röportaj konusu: Röportajcı: "Baharda kullanılan tasarım kalıpları hakkında konuşalım mı?"

JDK'da hangi tasarım modelleri kullanılıyor, İlkbaharda hangi tasarım modelleri kullanılıyor? Bu iki soru görüşmelerde daha sık karşımıza çıkıyor. İlkbahardaki tasarım kalıplarını internette araştırdım.Açıklamalar hemen hemen aynı ve çoğu eski. Bu yüzden kendim özetlemem birkaç gün sürdü Kişisel yeteneğim sınırlı olduğu için yazıda herhangi bir hataya işaret edebilirsiniz. Ek olarak, makalenin uzunluğu sınırlıdır, ben sadece tasarım desenlerinin yorumunu ve bazı kaynak kodlarını tek vuruşta verdim Bu makalenin temel amacı, Spring'deki yaygın tasarım desenlerini gözden geçirmektir.

Tasarım Modelleri, nesne yönelimli yazılım geliştirmede en iyi bilgisayar programlama uygulamalarını temsil eder. Yay çerçevesinde farklı tasarım desenleri yaygın olarak kullanılmaktadır, bir bakalım tasarım desenleri nelerdir?

Kontrolü Ters Çevirme (IoC) ve Bağımlılık Enjeksiyonu (DI)

IoC (Kontrolün Tersine Çevrilmesi) Baharda çok önemli bir kavram, bir teknoloji değil, ayrıştırıcı bir tasarım fikri. Ana amacı, bağımlı nesneler arasında ayrıştırmayı sağlamak için "üçüncü taraf" ı (Baharda IOC konteyneri) kullanmaktır (IOC'nin nesneleri yönetmesi kolaydır, bunu kullanabilirsiniz), böylece kodlar arasındaki bağlantıyı azaltır . IOC bir model değil, bir ilkedir.Aşağıdaki modeller (ancak bunlarla sınırlı değildir) IoC ilkesini uygular.

ioc kalıpları

Spring IOC konteyneri bir fabrika gibidir.Bir nesne yaratmamız gerektiğinde, nesnenin nasıl yaratıldığını düşünmeden sadece yapılandırma dosyasını / açıklamayı yapılandırmamız gerekir. IOC konteyneri, nesneler oluşturmaktan, nesneleri birbirine bağlamaktan, bu nesneleri yapılandırmaktan ve bu nesnelerin yaratılıştan tamamen yok edilene kadar tüm yaşam döngüsünü işlemekten sorumludur.

Gerçek bir projede, bir Hizmet sınıfının alt katmanı olarak yüzlerce hatta binlerce sınıf varsa, Hizmeti somutlaştırmamız gerekir.Her seferinde Hizmetin tüm alt sınıflarının yapıcılarını bulmanız gerekebilir, bu da neden olabilir İnsanlar çıldırıyor. IOC kullanıyorsanız, yalnızca yapılandırmanız ve ardından gerektiğinde başvurmanız gerekir, bu da projenin sürdürülebilirliğini büyük ölçüde artırır ve geliştirme zorluğunu azaltır. Bahar IOC'nin anlaşılmasıyla ilgili olarak, bu cevabı Zhihu'dan okumanız tavsiye edilir: https://www.zhihu.com/question/23277575/answer/169698662, ki bu çok iyi.

Kontrol çevirme nasıl anlaşılır? Örneğin: "a nesnesi, b nesnesine bağlıdır. Nesne a'nın b nesnesini kullanması gerektiğinde, onu kendiniz oluşturmanız gerekir. Ancak, sistem IOC konteynerini sunduğunda, nesne a ve nesne b doğrudan teması kaybeder. Bu sırada A nesnesinin b nesnesini kullanması gerektiğinde, bir b nesnesi oluşturmak ve onu a "nesnesine enjekte etmek için IOC konteynerini belirtebiliriz. A nesnesinin bağımlı nesne b'yi elde etme süreci, aktif davranıştan pasif davranışa değişir ve kontrol tersine çevrilir Bu, kontrol tersine çevirme adının kökenidir.

DI (Dependecy Inject), kontrolün ters çevrilmesini gerçekleştirmek için bir tasarım modelidir. Bağımlılık enjeksiyonu, örnek değişkenlerini bir nesneye geçirmektir.

Fabrika tasarım deseni

Spring, BeanFactory veya ApplicationContext aracılığıyla fasulye nesneleri oluşturmak için fabrika modelini kullanır.

İkisinin karşılaştırılması:

  • BeanFactory: Gecikmeli enjeksiyon (sadece fasulye kullanıldığında enjekte edilir) BeanFactory ile karşılaştırıldığında daha az hafıza kaplar ve program daha hızlı başlar.
  • ApplicationContext: Kap başladığında, kullansanız da kullanmasanız da, tüm fasulyeleri aynı anda oluşturun. BeanFactory yalnızca en temel bağımlılık enjeksiyon desteğini sağlar. ApplicationContext, BeanFactory'yi genişletir.BeanFactory'nin işlevlerine ek olarak, ek işlevler vardır, bu nedenle genel geliştiriciler ApplicationContext'i daha fazla kullanacaktır.

ApplicationContext'in üç uygulama sınıfı:

  • ClassPathXmlApplication: Bağlam dosyasını bir sınıf yolu kaynağı olarak ele alın.
  • FileSystemXmlApplication: Bağlam tanımı bilgilerini dosya sistemindeki XML dosyasından yükleyin.
  • XmlWebApplicationContext: Web sistemindeki XML dosyalarından içerik tanımı bilgilerini yükleyin.
  • Misal:

    org.springframework.context.ApplicationContext'i içe aktar; import org.springframework.context.support.FileSystemXmlApplicationContext; public class Uygulaması { public static void main (String args) { ApplicationContext context = new FileSystemXmlApplicationContext ( "C: / work / IOC Kapsayıcıları / springframework.applicationcontext / src / main / kaynaklar / bean-factory-config.xml"); HelloApplicationContext obj = (HelloApplicationContext) context.getBean ("helloApplicationContext"); obj.getMsg (); } }
    Singleton tasarım deseni

    Sistemimizde, aslında sadece bir tanesine ihtiyacımız olan bazı nesneler vardır, örneğin: iş parçacığı havuzu, önbellek, iletişim kutusu, kayıt defteri, günlük nesnesi ve yazıcılar ve grafik kartları gibi aygıt sürücüleri olarak işlev gören nesneler. Aslında, bu tür nesnenin yalnızca bir örneği olabilir. Birden çok örnek oluşturulursa, anormal program davranışı, aşırı kaynak kullanımı veya tutarsız sonuçlar gibi bazı sorunlar ortaya çıkabilir.

    Tekli desen kullanmanın faydaları:

    • Sık kullanılan nesneler için, nesneler oluşturmak için harcanan zaman ihmal edilebilir, bu da bu ağır nesneler için önemli bir sistem yüküdür;
    • Yeni işlemlerin sayısı azaldıkça, sistem belleğini kullanma sıklığı da azalacak, bu da GC basıncını azaltacak ve GC duraklatma süresini kısaltacaktır.

    Baharda varsayılan fasulye kapsamı tek tondur (tek ton). Tekli kapsama ek olarak, bahardaki fasulye ayrıca aşağıdaki kapsamlara sahiptir:

    • prototip: Her istek yeni bir fasulye örneği oluşturacaktır.
    • istek: Her HTTP isteği, yalnızca mevcut HTTP isteğinde geçerli olan yeni bir fasulye üretir.
    • oturum: Her HTTP isteği, yalnızca mevcut HTTP oturumunda geçerli olan yeni bir fasulye üretir.
    • genel oturum: Küresel oturum kapsamı, yalnızca portal uygulamacığı tabanlı web uygulamalarında anlamlıdır, Spring5 gitti. Portlet, anlamsal kod parçaları (örneğin: HTML) oluşturabilen küçük bir Java Web eklentisidir. Portlet konteynerlerine dayanırlar ve sunucu uygulamaları gibi HTTP isteklerini işleyebilirler. Ancak, sunucu uygulamalarının aksine, her portletin farklı bir oturumu vardır

    Spring'in singleton uygulama şekli:

    • xml: < bean id = "userService" class = "top.snailclimb.UserService" kapsam = "singleton" / >
    • Yorum: @Scope (value = "singleton")

    Spring, singleton kaydını gerçekleştirmek için özel ConcurrentHashMap yoluyla tekli modu uygular. Spring'in bir singleton uygulaması için temel kod aşağıdaki gibidir:

    // ConcurrentHashMap (iş parçacığı güvenliği) aracılığıyla tekil kayıt gerçekleştirin özel final Haritası < Dize, Nesne > singletonObjects = yeni ConcurrentHashMap < Dize, Nesne > (64); public Object getSingleton (String beanName, ObjectFactory < ? > singletonFactory) { Assert.notNull (beanName, "'beanName' boş olmamalıdır"); senkronize (this.singletonObjects) { // Önbellekte bir örnek olup olmadığını kontrol edin Object singletonObject = this.singletonObjects.get (beanName); eğer (singletonObject == null) { // ... birçok kod atlandı Deneyin { singletonObject = singletonFactory.getObject (); } // ... birçok kod atlandı // Örnek nesne yoksa, onu tekli kayıt defterine kaydederiz. addSingleton (beanName, singletonObject); } return (singletonObject! = NULL_OBJECT? singletonObject: null); } } // Nesneyi singleton kayıt defterine ekleyin korumalı void addSingleton (String beanName, Object singletonObject) { senkronize (this.singletonObjects) { this.singletonObjects.put (beanName, (singletonObject! = null? singletonObject: NULL_OBJECT)); } } }
    Ajans tasarım modeli

    AOP'de Proxy Modunun Uygulanması

    AOP (Unsur Odaklı Programlama: Unsur Odaklı Programlama), sistemin kopyalanmasını azaltmak için işle ilgili olmayan ancak iş modülleri tarafından çağrılan mantık veya sorumlulukları (işlem işleme, günlük yönetimi, erişim kontrolü vb.) Kapsayabilir. , Modüller arasındaki bağlantı derecesini azaltın ve gelecekteki ölçeklenebilirliği ve sürdürülebilirliği kolaylaştırın.

    Spring AOP, dinamik proxy'ye dayanır , Proxy alınacak nesne bir arabirim uygularsa, Spring AOP kullanacaktır JDK Proxy , Bir proxy nesnesi oluşturmak ve arabirimi uygulamayan nesneler için, JDK Proxy'yi proxy olarak kullanamazsınız, bu sefer Spring AOP kullanacaktır Cglib , Bu sefer Spring AOP kullanacak Cglib Aşağıdaki şekilde gösterildiği gibi, proxy nesnesinin bir alt sınıfını proxy olarak oluşturun:

    SpringAOP Süreci

    Elbette AspectJ'yi de kullanabilirsiniz, Spring AOP, AspectJ'yi entegre etmiştir, AspectJ, Java ekosistemindeki en eksiksiz AOP çerçevesi olarak görülmelidir.

    AOP'yi kullandıktan sonra, bazı ortak işlevleri soyutlayabilir ve bunları doğrudan ihtiyaç duyulan yerlerde kullanabiliriz, bu da kod miktarını büyük ölçüde basitleştirir. Sistem ölçeklenebilirliğini de artıran yeni işlevler eklememiz gerektiğinde de kullanışlıdır. AOP, günlük işlevi ve işlem yönetimi gibi senaryolarda kullanılır.

    Spring AOP ve AspectJ AOP arasındaki fark nedir?

    Spring AOP bir çalışma zamanı geliştirmesidir, AspectJ ise bir derleme zamanı geliştirmesidir. Spring AOP, Proxying'e dayanır, AspectJ ise Bytecode Manipulation'a dayanır.

    Spring AOP, AspectJ'yi entegre etti ve AspectJ, Java ekosistemindeki en eksiksiz AOP çerçevesi olarak görülmelidir. AspectJ, Spring AOP'den daha güçlüdür, ancak Spring AOP nispeten daha basittir.

    Daha az yönümüz varsa, ikisi arasında performans açısından çok az fark vardır. Ancak, çok fazla özellik olduğunda, Spring AOP'den çok daha hızlı olan AspectJ'yi seçmek en iyisidir.

    Şablon yöntemi

    Şablon yöntem modeli, bazı adımları alt sınıflara doğru geciktirirken, çalışan bir algoritmanın iskeletini tanımlayan davranışsal bir tasarım modelidir. Şablon yöntemi, alt sınıfların, bir algoritmanın yapısını değiştirmeden bir algoritmanın belirli belirli adımlarının uygulanmasını yeniden tanımlamasına izin verir.

    Şablon yöntemi UML diyagramı

    public abstract class Template { // Bu bizim şablon yöntemimizdir public final void TemplateMethod () { PrimitiveOperation1 (); PrimitiveOperation2 (); PrimitiveOperation3 (); } korumalı void PrimitiveOperation1 () { // Mevcut sınıf uygulaması } // Alt sınıflar tarafından uygulanan yöntemler korumalı soyut geçersiz PrimitiveOperation2 (); korumalı soyut geçersiz PrimitiveOperation3 (); } public class TemplateImpl, Template { @Override public void PrimitiveOperation2 () { // Mevcut sınıf uygulaması } @Override public void PrimitiveOperation3 () { // Mevcut sınıf uygulaması } }

    Spring'de, jdbcTemplate, hibernateTemplate ve veritabanı işlemleri için Şablon ile biten diğer sınıflar şablon modunu kullanır. Normal koşullar altında, şablon modunu uygulamak için kalıtımı kullanırız, ancak Spring bu yöntemi kullanmaz, ancak yalnızca kodun yeniden kullanımının etkisini elde etmekle kalmayan, aynı zamanda esnekliği artıran şablon yöntemi moduyla birlikte Geri Çağırma modunu kullanır. .

    Gözlemci modu

    Gözlemci modeli bir nesne davranış modelidir. Bir nesne ile nesne arasındaki bağımlılığı temsil eder.Bir nesne değiştiğinde, nesnenin bağlı olduğu nesneler de tepki verir. Spring olay odaklı model, gözlemci modelinin klasik bir uygulamasıdır. Spring olay güdümlü model çok kullanışlıdır ve birçok senaryoda kodumuzu ayırabilir. Örneğin her ürün eklediğimizde ürün indeksini güncellememiz gerekiyor, şu anda bu sorunu çözmek için gözlemci modunu kullanabiliriz.

    İlkbahar olay odaklı modelde üç rol

    Etkinlik rolü

    ApplicationEvent (org.springframework.context paketi altında) bir olay görevi görür.Bu, java.util.EventObject'i miras alan ve java.io.Serializable arabirimini uygulayan soyut bir sınıftır.

    Aşağıdaki olaylar varsayılan olarak Spring'de mevcuttur ve bunların tümü ApplicationContextEvent'in (ApplicationContextEvent'ten devralınan) uygulamalarıdır:

    • ContextStartedEvent: ApplicationContext başlatıldıktan sonra tetiklenen olay;
    • ContextStoppedEvent: ApplicationContext durdurulduktan sonra tetiklenen olay;
    • ContextRefreshedEvent: ApplicationContext başlatıldıktan veya yenilendikten sonra tetiklenen olay;
    • ContextClosedEvent: ApplicationContext kapatıldıktan sonra tetiklenen olay.

    ApplicationEvent-Subclass

    Etkinlik dinleyici rolü

    ApplicationListener, bir olay dinleyicisi olarak işlev görür ve ApplicationEvent'i işlemek için yalnızca bir onApplicationEvent () yönteminin tanımlandığı bir arabirimdir. ApplicationListener arabirim sınıfının kaynak kodu aşağıdaki gibidir: Arabirimdeki olayların yalnızca ApplicationEvent'i gerçekleştirmesi gerektiği arabirim tanımından görülebilir. Bu nedenle, İlkbaharda, izleme olayını tamamlamak üzere onApplicationEvent () yöntemini uygulamak için yalnızca ApplicationListener arabirimini uygulamamız gerekir.

    paket org.springframework.context; import java.util.EventListener; @FunctionalInterface genel arabirim ApplicationListener < E, ApplicationEvent'i genişletir > EventListener { void onApplicationEvent (E var1); }

    Etkinlik yayıncısı rolü

    ApplicationEventPublisher, olayların yayıncısı olarak hareket eder ve aynı zamanda bir arayüzdür.

    @FunctionalInterface genel arayüz ApplicationEventPublisher { varsayılan void publishEvent (ApplicationEvent olayı) { this.publishEvent ((Nesne) olayı); } void publishEvent (Nesne var1); }

    ApplicationEventPublisher arabiriminin publishEvent () yöntemi, AbstractApplicationContext sınıfında uygulanmaktadır.Bu yöntemin uygulamasını okurken, olayın aslında ApplicationEventMulticaster aracılığıyla yayınlandığını göreceksiniz. Spesifik içerik çok fazla, bu yüzden burada analiz etmeyeceğim ve daha sonra bahsetmek için bir makale yazabilirim.

    Baharın olay akışı özeti

  • Bir olay tanımlayın: ApplicationEvent'ten miras alınan bir olay uygulayın ve ilgili kurucuyu yazın;
  • Bir olay dinleyicisi tanımlayın: ApplicationListener arabirimini uygulayın ve onApplicationEvent () yöntemini geçersiz kılın;
  • Mesajları yayınlamak için olay yayıncısını kullanın: Mesajları, ApplicationEventPublisher'ın publishEvent () yöntemi ile yayınlayabilirsiniz.
  • Misal:

    // Bir olay tanımlayın, ApplicationEvent'ten devralın ve karşılık gelen kurucuyu yazın public class DemoEvent ApplicationEvent'i genişletir { özel statik son uzun serialVersionUID = 1L; private String mesajı; public DemoEvent (Nesne kaynağı, Dize mesajı) { süper (kaynak); this.message = mesaj; } public String getMessage () { geri dönüş mesajı; } // Bir olay dinleyicisi tanımlayın, ApplicationListener arayüzünü uygulayın ve onApplicationEvent () yöntemini geçersiz kılın; @Bileşen public class DemoListener ApplicationListener uygular < DemoEvent > { // Mesajları almak için onApplicationEvent kullanın @Override public void onApplicationEvent (DemoEvent olayı) { Dize msg = event.getMessage (); System.out.println ("Alınan bilgi:" + msg); } } // Bir olay yayınlamak için, mesajı ApplicationEventPublisher'ın publishEvent () yöntemi aracılığıyla yayınlayabilirsiniz. @Bileşen public class DemoPublisher { @Autowired ApplicationContext applicationContext; public void yayınlama (Dize mesajı) { //Olay sonrası applicationContext.publishEvent (yeni DemoEvent (bu, mesaj)); } }

    DemoPublisher'ın publish () yöntemi çağrıldığında, örneğin demoPublisher.publish ("Merhaba"), konsol çıktı alır: Alınan mesaj: Merhaba.

    Adaptör modu

    Bağdaştırıcı Kalıbı, bir arabirimi müşterinin istediği başka bir arabirime dönüştürür Bağdaştırıcı Kalıbı, arabirimle uyumsuz olan sınıfların birlikte çalışmasına izin verir ve diğer adı Sarmalayıcı'dır.

    AOP yayında adaptör düzeni

    Spring AOP uygulamasının proxy moduna dayandığını biliyoruz, ancak Spring AOP'nin geliştirmesi veya tavsiyesi adaptör modunu kullanıyor ve ilgili arayüz AdvisorAdapter. Yaygın olarak kullanılan Tavsiye türleri şunlardır: BeforeAdvice (hedef yöntem çağrılmadan önce, ön bildirim), AfterAdvice (hedef yöntem çağrıldıktan sonra, bildirim sonrası), AfterReturningAdvice (hedef yöntem çalıştırıldıktan sonra, geri dönmeden önce) vb. Her bir Tavsiye (bildirim) türüne karşılık gelen bir durdurucu vardır: MethodBeforeAdviceInterceptor, AfterReturningAdviceAdapter, AfterReturningAdviceInterceptor. Spring tarafından önceden tanımlanmış bildirimler, ilgili adaptör aracılığıyla MethodInterceptor arabirimi (yöntem durdurucu) türündeki nesnelere uyarlanmalıdır (örneğin, MethodBeforeAdviceInterceptor, MethodBeforeAdvice'i uyarlamaktan sorumludur).

    İlkbahar MVC'sinde adaptör düzeni

    Spring MVC'de DispatcherServlet, istek bilgilerine göre HandlerMapping'i çağırır ve isteğe karşılık gelen İşleyiciyi ayrıştırır. İlgili İşleyiciye (yani, genellikle çağırdığımız Denetleyici denetleyicisine) ayrıştırıldıktan sonra, HandlerAdapter bağdaştırıcısı tarafından işlenmeye başlar. HandlerAdapter beklenen arabirimdir, belirli bağdaştırıcı uygulama sınıfı, hedef sınıfı uyarlamak için kullanılır ve Controller, uyarlanması gereken sınıftır.

    Adaptör modelini Spring MVC'de neden kullanmalı? Spring MVC'de birçok Denetleyici türü vardır ve farklı Denetleyici türleri istekleri farklı şekillerde işler. Bağdaştırıcı modunu kullanmazsanız, DispatcherServlet doğrudan ilgili Denetleyici türünü alır, aşağıdaki kod gibi kendi kendinize karar vermeniz gerekir:

    if (mappedHandler.getHandler () MultiActionController örneği) { ((MultiActionController) mappedHandler.getHandler ()). Xxx } else if (mappedHandler.getHandler () XXX örneği) { ... } else if (...) { ... }

    Başka bir Denetleyici türü eklersek, yukarıdaki koda başka bir yargı beyanı eklememiz gerekir.Bu form, programın sürdürülmesini zorlaştırır ve tasarım modelinde uzantılara açık ve değişikliklere kapalı açılış ve kapanış ilkelerini ihlal eder.

    Dekoratör modu

    Dekoratör modu, nesneye dinamik olarak bazı ek özellikler veya davranışlar ekleyebilir. Miras kullanmaya kıyasla, dekoratör modeli daha esnektir. Basitçe söylemek gerekirse, orijinal işlevi değiştirmemiz gerektiğinde, ancak orijinal kodu doğrudan değiştirmek istemediğimizde, orijinal kodu kapsayacak bir Dekoratör tasarlayın. Aslında, JDK'da, InputStream ailesi gibi dekoratör modunu kullanan birçok yer vardır, InputStream sınıfı altında FileInputStream (dosyaları okuma), BufferedInputStream (önbelleği artırın, dosya okuma hızını büyük ölçüde artırın) ve diğer alt sınıflar InputStream'i değiştirmiyor Kod durumunda işlevselliğini genişletti.

    Dekoratör modunun şematik diyagramı

    DataSource'u Spring'de yapılandırırken, DataSource farklı veritabanları ve veri kaynakları olabilir. Orijinal kodu değiştirmeden müşteri ihtiyaçlarına göre farklı veri kaynakları arasında dinamik olarak geçiş yapabilir miyiz? Şu anda, dekoratör modunu kullanacağız (Bu noktada belirli ilkeleri çok fazla anlamıyorum). Spring'de kullanılan sarmalayıcı desen, sınıf adında Sarmalayıcı veya Dekoratör içerir. Bu sınıflar temelde dinamik olarak bir nesneye bazı ek sorumluluklar ekler.

    sonuç olarak

    Yay çerçevesinde hangi tasarım modelleri kullanılır:

    • Fabrika tasarım deseni : Spring, BeanFactory ve ApplicationContext aracılığıyla fasulye nesneleri oluşturmak için fabrika modunu kullanır.
    • Ajans tasarım modeli : Yay AOP işlevinin uygulanması.
    • Singleton tasarım deseni : İlkbahardaki fasulye varsayılan olarak tek tondur.
    • Şablon yöntemi modeli : Spring, jdbcTemplate, hibernateTemplate ve veritabanı işlemleri için Template ile biten diğer sınıflarda şablon modunu kullanırlar.
    • Sarıcı tasarım deseni : Projemizin birden çok veri tabanına bağlanması gerekiyor ve farklı müşteriler her ziyarette ihtiyaçlarına göre farklı veri tabanlarını ziyaret edecek. Bu model, müşteri ihtiyaçlarına göre farklı veri kaynakları arasında dinamik olarak geçiş yapmamızı sağlar.
    • Gözlemci modu: Bahar olay odaklı modeli, gözlemci modelinin klasik bir uygulamasıdır.
    • Adaptör modu : Spring AOP'nin geliştirmesi veya tavsiyesi (Tavsiye) adaptör modelini kullanır ve yay MVC ayrıca Kontrolöre uyum sağlamak için adaptör modelini kullanır.
    • ...
    40'lı yaşlarında işinden ayrıldı ve bir boya fırçası aldı, orijinal 3D cam resmi insanları iyi ve iyileşmiş gösteriyordu.
    önceki
    81 yaşındaki adam yanlışlıkla bir tasarım dehası olduğunu keşfetti ve geleceği tahmin etti, seyahat etmiş olabilir mi?
    Sonraki
    Wu Yishu 613, Tsinghua Üniversitesi'ne işaret ediyor Çin Şiir Yarışması'nın şampiyonu aslında bilim konusunda yetenekli bir kadın mı?
    Robot süpürgeleri gençler arasında popülerdir! 618 Alışveriş Festivalinde bu sıcak ürünlerle mi başladınız?
    springcloud-microservice hızla dağıtılmış bir sistem oluşturur
    JeeWeb Çevik Geliştirme Platformu
    "Onyedi" "Haber" 190617 "Batan güneşteki çocuk" Junhui, rahat ve rahat günlük yaşamı gösterir
    "NCT" "Paylaş" 190617 NCT127 GIF'in ve çıkartmaların yeni Superhuman versiyonu çok popüler
    Spring + SpringMVC + Mybatis dağıtılmış çevik geliştirme sistemi mimarisine dayalı
    Honor 618, 40 şampiyonluk yükseltti, Honor 20 PRO'nun ilk satışı büyük bir başarı
    "IT House Public Test Works" Roborock T4 Değerlendirme: 1699 LDS + yarı saydam tasarım
    İki çocuğunun fotoğraflarını çekti ama büyülü bir dünya yarattı ve internette popüler oldu.
    Japon tasarımcılar 2020 Tokyo Olimpiyatları'nı karşılamak için dünyanın bayraklarını erkek tanrılara dönüştürüyor ve Çin yakışıklı
    Honor 618, 40 şampiyonluk yükseltti, Honor 20 PRO'nun ilk satışı büyük bir başarı
    To Top