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?
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.
Spring, BeanFactory veya ApplicationContext aracılığıyla fasulye nesneleri oluşturmak için fabrika modelini kullanır.
İkisinin karşılaştırılması:
ApplicationContext'in üç uygulama sınıfı:
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 (); } }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ı:
Baharda varsayılan fasulye kapsamı tek tondur (tek ton). Tekli kapsama ek olarak, bahardaki fasulye ayrıca aşağıdaki kapsamlara sahiptir:
Spring'in singleton uygulama şekli:
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)); } } }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ö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 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:
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
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.
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, 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.
Yay çerçevesinde hangi tasarım modelleri kullanılır: