Alan Enjeksiyonu tam olarak nedir ve nasıl önlenir?


130

Spring MVC ve Portletlerle ilgili bazı yazılarda alan enjeksiyonunun tavsiye edilmediğini okudum . Anladığım kadarıyla, alan enjeksiyonu şu şekilde bir Fasulye enjekte ettiğiniz zamandır @Autowired:

@Component
public class MyComponent {
    @Autowired
    private Cart cart;
}

Araştırmam sırasında ayrıca yapıcı enjeksiyonu hakkında da okudum :

@Component
public class MyComponent {
    private final Cart cart;

    @Autowired
    public MyComponent(Cart cart){
       this.cart = cart;
    }
}

Bu enjeksiyon türlerinin her ikisinin de avantajları ve dezavantajları nelerdir?


DÜZENLEME 1: Bu soru yinelenen olarak işaretlenmiş gibi bu soruya ben bunu kontrol etti. Çünkü ne soruda ne de cevaplarda herhangi bir kod örneği yok, tahminimle hangi enjeksiyon tipini kullandığımı doğru yapıp yapmadığım açık değil.


3
Alan enjeksiyonu tarif ettiğiniz kadar kötüyse, Bahar buna neden izin veriyor? Alan enjeksiyonunun, kodu daha okunaklı ve daha az ayrıntılı hale getirmede kendine has faydaları vardır. Kodlamanızda yeterince disiplinliyseniz, alan enjeksiyonu kullansanız bile işlerin bozulmayacağından emin olabilirsiniz.
küller

1
@ashes Çünkü o zamanlar harika bir özellikti ve etkileri tamamen düşünülmemişti. Var olanla aynı sebep Date(int,int,int).
chrylis

Yanıtlar:


225

Enjeksiyon türleri

Bağımlılıkların bir fasulyeye nasıl enjekte edilebileceğine dair üç seçenek vardır:

  1. Bir kurucu aracılığıyla
  2. Ayarlayıcılar veya diğer yöntemler aracılığıyla
  3. Yansıma yoluyla, doğrudan alanlara

3. seçeneği kullanıyorsunuz. @AutowiredDoğrudan tarlanızda kullandığınızda olan budur .


Enjeksiyon talimatları

Spring tarafından önerilen genel bir kılavuz ( Yapıcı tabanlı DI veya Ayarlayıcı tabanlı DI ile ilgili bölümlere bakın ) aşağıdaki gibidir:

  • Zorunlu bağımlılıklar için veya değişmezliği hedeflerken yapıcı enjeksiyonu kullanın
  • İsteğe bağlı veya değiştirilebilir bağımlılıklar için ayarlayıcı enjeksiyon kullanın
  • Çoğu durumda alan enjeksiyonundan kaçının

Alan enjeksiyon sakıncaları

Alan enjeksiyonunun kabul edilmemesinin nedenleri aşağıdaki gibidir:

  • Yapıcı enjeksiyonla yapabileceğiniz gibi değişmez nesneler oluşturamazsınız
  • Sınıflarınız DI kabınız ile sıkı bağlantıya sahiptir ve onun dışında kullanılamaz
  • Sınıflarınız yansıtma olmadan somutlaştırılamaz (örneğin birim testlerinde). Bunları somutlaştırmak için DI kapsayıcısına ihtiyacınız vardır, bu da testlerinizi daha çok entegrasyon testleri gibi yapar
  • Gerçek bağımlılıklarınız dışarıdan gizlenir ve arayüzünüze yansıtılmaz (yapıcılar veya yöntemler)
  • On bağımlılığa sahip olmak gerçekten çok kolay. Yapıcı enjeksiyon kullanıyor olsaydınız, on argümana sahip bir yapıcınız olurdu, bu da bir şeyin şüpheli olduğuna işaret ederdi. Ancak, alan enjeksiyonu kullanarak süresiz olarak enjekte edilen alanlar ekleyebilirsiniz. Çok fazla bağımlılığa sahip olmak, sınıfın genellikle birden fazla şey yaptığını ve Tek Sorumluluk İlkesini ihlal edebileceğini gösteren bir işarettir.

Sonuç

İhtiyaçlarınıza bağlı olarak, öncelikle yapıcı enjeksiyonu veya bazı yapıcı ve ayarlayıcı enjeksiyon karışımını kullanmalısınız. Alan enjeksiyonunun birçok dezavantajı vardır ve bundan kaçınılmalıdır. Alan enjeksiyonunun tek avantajı, tüm eksilerini aşmayan, yazmanın daha uygun olmasıdır.


daha fazla okuma

Alan enjeksiyonunun neden genellikle tavsiye edilmediğiyle ilgili bir blog yazısı yazdım: Alan Bağımlılık Enjeksiyonunun Zararlı Olarak Değerlendirilmesi .


12
Genel olarak iyi bir fikir değildir ve dünyaya "alan enjeksiyonundan kaçınılmalıdır" demek hoş değildir. Artıları ve kontratları gösterin ve başkalarının karar vermesine izin verin;) Pek çok insanın başka deneyimleri ve olaylara kendi bakış açıları vardır.
diyetisyen

6
Burada durum bu olabilir, ancak topluluğun bir şeyi caydırmak için genel bir fikir birliğine vardığı başka durumlar da vardır. Örneğin, Macar Gösterimi'ni ele alalım.
Jannik

Test edilebilirlik ve bağımlılık görünürlüğü olarak bazı iyi puanlar veriyorsunuz ama ben hepsine katılmıyorum. Yapıcı enjeksiyonunun sakıncaları yok mu? Gerçek çağrı kompozisyonlarını gerçekleştiren sınıfta enjekte edilecek 5 veya 6 alana sahip olmak arzu edilebilir. Ben de değişmezliğe katılmıyorum. Son alanlara sahip olmak, bir sınıfın değişmez olması için zorunlu değildir. Bu tercih edilebilir. Hangisi çok farklı.
davidxxx

Sanırım "Zorunlu bağımlılıklar için veya değişmezliği hedeflerken " demek istediniz
Alex Terreaux

1
Cevabın başında bahar belgelerine bağlantı veren bağlantıya atıfta bulunuyordum
Vojtech Ruzicka

47

Bu, yazılım geliştirmede hiç bitmeyen tartışmalardan biridir, ancak sektördeki önemli etkileyiciler konu hakkında daha fazla fikir sahibi oluyor ve daha iyi bir seçenek olarak yapıcı enjeksiyonu önermeye başladı.

Yapıcı enjeksiyon

Artıları:

  • Daha iyi test edilebilirlik . Birim testlerinde herhangi bir alay kitaplığına veya Spring bağlamına ihtiyacınız yoktur. Yeni anahtar kelimeyle test etmek istediğiniz bir nesne oluşturabilirsiniz . Bu tür testler her zaman daha hızlıdır çünkü yansıtma mekanizmasına dayanmazlar. ( Bu soru 30 dakika sonra soruldu . Yazar yapıcı enjeksiyon kullanmış olsaydı görünmezdi).
  • Değişmezlik . Bağımlılıklar ayarlandıktan sonra değiştirilemezler.
  • Daha güvenli kod . Bir kurucunun çalıştırılmasından sonra, parametre olarak iletilen her şeyi doğrulayabileceğiniz için nesneniz kullanıma hazırdır. Nesne hazır olabilir veya olmayabilir, arada bir durum yoktur. Alan enjeksiyonu ile, nesne kırılgan olduğunda bir ara adım başlatırsınız.
  • Zorunlu bağımlılıkların daha net ifadesi . Alan enjeksiyonu bu konuda belirsizdir.
  • Geliştiricilerin tasarım hakkında düşünmesini sağlar . dit, aslında kötü bir tasarımın ve Tanrı nesnesi anti-modelin işareti olan 8 parametreli bir kurucu hakkında yazdı . Bir sınıfın kurucusunda veya alanlarda 8 bağımlılığı olup olmaması önemli değildir, her zaman yanlıştır. İnsanlar alanlardan ziyade bir kurucuya daha fazla bağımlılık eklemek konusunda daha isteksizdir. Beyninize bir süre durmanız ve kod yapınız hakkında düşünmeniz gerektiğine dair bir sinyal olarak çalışır.

Eksileri:

  • Daha fazla kod (ancak modern IDE'ler acıyı hafifletir).

Temel olarak, alan enjeksiyonu tam tersidir.


1
test edilebilirlik, evet, tarlaya enjekte edilen fasulyelerle dalga geçmek benim için bir kabustu. Bir keresinde contsructor enjeksiyonu kullanılır, herhangi bir gereksiz mocking yapmak zorunda değildir
kenobiwan

25

Tat meselesi. Bu senin kararın.

Ama neden yapıcı enjeksiyon kullanmadığımı açıklayabilirim .

  1. Ben bütün bir yapıcı uygulamak istemiyoruz @Service, @Repositoryve @Controllerfasulye. Demek istediğim, yaklaşık 40-50 fasulye var. Her seferinde yeni bir alan eklersem kurucuyu genişletmem gerekir. Hayır, istemiyorum ve zorunda da değilim.

  2. Ya Fasulyeniz (Servis veya Kontrolör) çok sayıda başka fasulyenin enjekte edilmesini gerektiriyorsa? 4+ parametresi olan bir kurucu çok çirkin.

  3. CDI kullanıyorsam, kurucu beni ilgilendirmiyor.


DÜZENLEME 1 : Vojtech Ruzicka şunları söyledi:

sınıfın çok fazla bağımlılığı var ve muhtemelen tek sorumluluk ilkesini ihlal ediyor ve yeniden düzenlenmeli

Evet. Teori ve gerçeklik. İşte bir örnek: DashboardControllertek yola eşlenmiş *:8080/dashboard.

My DashboardController, bir gösterge tablosunda / sisteme genel bakış sayfasında görüntülemek için diğer hizmetlerden birçok bilgi toplar. Bu tek denetleyiciye ihtiyacım var. Bu yüzden sadece bu yolu güvenceye almalıyım (temel kimlik doğrulama veya kullanıcı rolü filtresi).

DÜZENLEME # 2 : Herkes kurucudaki 8 parametreye odaklandığından ... Bu gerçek dünya örneğiydi - bir müşterinin eski kodu. Ben bunu değiştirdim. Aynı argümantasyon 4+ parametre için benim için de geçerli.

Her şey örnek oluşturma değil, kod enjeksiyonu ile ilgilidir.


34
8 bağımlılığı olan çok çirkin bir kurucu aslında harika çünkü bir şeylerin yanlış olduğu, sınıfın çok fazla bağımlılığı olduğu ve muhtemelen tek sorumluluk ilkesini ihlal ettiği ve yeniden düzenlenmesi gerektiğine dair kırmızı bir bayrak. Aslında iyi bir şey.
Vojtech Ruzicka

6
@VojtechRuzicka Kesinlikle hoş değil ama bazen bundan kaçınamazsınız.
dieter

4
40-50'yi bir kenara bırakıp 3 şeklinde bir temel kural, herhangi bir sınıf için bağımlılıkların yeniden düzenleme yapmanız gerektiğinin bir işareti olması gerektiğini söyleyebilirim. 40 bağımlılığı olan bir sınıfın tek bir sorumluluk müdürüne veya açık / kapalı müdürüne bağlı kalması mümkün değildir.
Amin J

4
@AminJ Kural harika, ama gerçek farklı. Çalıştığım şirket 20 yıldan fazla ve çok sayıda eski kodumuz var. Yeniden düzenleme iyi bir fikirdir, ancak maliyeti yüksektir. Ayrıca neden söylüyorum bilmiyorum ama 40-50 bağımlılıktan bahsetmedim, 40-50 fasulye, bileşenler, modüller ...
dieter

7
@dit, durumunuz açıkça teknik borcun optimumun altında seçimler yapmanıza neden olduğu bir durumdur. Kendi sözlerinizle, karar verme sürecinizin 20 yıldan daha eski olan eski koddan önemli ölçüde etkilendiği bir durumdasınız. Yeni bir projeye başlarken, yapıcı enjeksiyon yerine yine de alan enjeksiyonu önerir misiniz? Belki hangi durumlarda alan enjeksiyonunu seçeceğinizi belirtmek için cevabınıza bir uyarı koymalısınız.
Umar Farooq Khawaja

0

Bir yorum daha - Vojtech Ruzicka, Spring'in fasulyeyi üç şekilde enjekte ettiğini belirtti (en fazla puanla cevap):

  1. Bir kurucu aracılığıyla
  2. Ayarlayıcılar veya diğer yöntemler aracılığıyla
  3. Yansıma yoluyla, doğrudan alanlara

Bu cevap YANLIŞ - çünkü HER TÜRLÜ ENJEKSİYON YAYI YANSIMAYI KULLANIR! IDE kullanın, ayarlayıcı / yapıcı üzerinde kesme noktası ayarlayın ve kontrol edin.

Bu bir zevk meselesi olabilir ama aynı zamanda bir CASE meselesi de olabilir. @dieter, alan enjeksiyonunun daha iyi olduğu durumlarda mükemmel bir durum sağladı. Spring bağlamını oluşturan entegrasyon testlerinde alan enjeksiyonu kullanıyorsanız - sınıfın test edilebilirliğine sahip argüman da geçersizdir - testlerde daha sonra entegrasyon testlerinize yazmak istemiyorsanız;)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.