Spring'de kendi kendine örneklenen bir nesneye bağımlılıklar nasıl enjekte edilir?


128

Diyelim ki bir sınıfımız var:

public class MyClass {
    @Autowired private AnotherBean anotherBean;
}

Sonra bu sınıfın bir nesnesini oluşturduk (veya başka bir çerçeve bu sınıfın örneğini yarattı).

MyClass obj = new MyClass();

Hala bağımlılıkları enjekte etmek mümkün mü? Gibi bir şey:

applicationContext.injectDependencies(obj);

(Sanırım Google Guice'de böyle bir şey var)

Yanıtlar:


194

Bunu autowireBean()yöntemini kullanarak yapabilirsiniz AutowireCapableBeanFactory. Ona rastgele bir nesne geçirirsiniz ve Spring ona kendi yarattığı bir şey gibi davranır ve çeşitli otomatik kablolama bit ve parçalarını uygular.

Ele almak için AutowireCapableBeanFactory, sadece bu autowire:

private @Autowired AutowireCapableBeanFactory beanFactory;

public void doStuff() {
   MyBean obj = new MyBean();
   beanFactory.autowireBean(obj);
   // obj will now have its dependencies autowired.
}

İyi cevap (+1). Otomatik kablolamanın nasıl gerçekleştiğini etkileyebileceğiniz ikinci bir yöntem de var: static.springsource.org/spring/docs/3.0.x/javadoc-api/org/…
Sean Patrick Floyd

Ama ya iki nesnem varsa ve ilk önce otomatik tellerim varsa. Autowire fasulye fabrikası bu durumda bağımlılıklarla nasıl ilgileniyor?
Vadim Kirilchuk

3
Bu aslında kötü bir model. MyBean'i gerçekten bu şekilde kullanıyorsanız, neden parametre olarak AnotherBean ile kurucuya sahip olmuyorsunuz? Gibi bir şey: codeözel @Autowired AnotherBean bean; public void doStuff () {MyBean obj = new MyBean (bean); } code. Görünüşe göre, tüm bu ek açıklamalarla insanlar gerçekten kafaları karışıyor ve 1. günden beri java SDK'da bulunan temel kalıbı kullanmıyorlar. :(
Denis

3
Katılıyorum - Bahar tüm dili yeniden tanımladı. Şimdi arayüzleri somut sınıflar olarak, sınıf örnekleri olarak yöntemler ve yeni ve iyi bir tasarımla yaptığınız şeyi yapmanın her tür karmaşık ve kodlama ağır yöntemlerini kullanıyoruz.
Rodney P. Barbati

@Denis MyBean'in gerçek sınıfın ihtiyaç duymadığı bağımlılıkları varsa, sadece bir sınıfı örneklemek için aslında var olmayan bağımlılıkları kaydediyorsunuz, yani gerçekten bir fark yok.
Dalton

17

Ayrıca MyClass'ınızı @Configurable ek açıklaması ile de işaretleyebilirsiniz:

@Configurable
public class MyClass {
   @Autowired private AnotherClass instance
}

Daha sonra yaratma sırasında otomatik olarak bağımlılıklarını enjekte edecektir. Ayrıca <context:spring-configured/>uygulamanızın bağlamında xml olmalıdır.


2
Galz666, yönteminiz yapmak istediğim şey için çok daha temiz görünüyor. Ancak onu çalıştıramıyorum. Hiçbir xml dosyam yok ve tamamen Java yapılandırması kullanıyorum. Eşdeğeri var mı <context:spring-configured/>?
masstroy

1
Bu temiz bir çözümdür, ancak biraz daha fazla çaba gerektirir: Yukarıda iimuhin'de gösterildiği gibi yükleme zamanı dokumasını kullanmalısınız veya projeye AspectJ derleyicisini eklemelisiniz. Adından da anlaşılacağı gibi yükleme süresi, çalışma zamanında ek maliyete neden olacaktır.
jsosnowski

4

Sadece aynı ihtiyacı aldım ve benim durumumda zaten erişime sahip olan Spring yönetilemeyen java sınıfının içindeki mantıktı ApplicationContext. Scaffman'dan ilham aldı. Çözen:

AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory();
factory.autowireBean(manuallyCreatedInstance);

3

@ Glaz666 yanıtında belirtilen @Configurableyaklaşımı takip eden çözümümü paylaşmak istedim çünkübriefly

  • Cevap @skaffman tarafından yaklaşık 10 yaşında olduğunu ve iyi değil yeterince anlamına gelmez veya iş yapmaz
  • @ Glaz666'nın cevabı kısa ve sorunumu çözmeme gerçekten yardımcı olmadı, ancak beni doğru yönü gösterdi

Kurulumum

  1. Spring Boot 2.0.3 ile Spring Neo4j & Aop starts(yine de alakasız)
  2. Yaklaşımı kullanarak Spring Boothazır olduğunda bir fasulyeyi örnekleyin @Configurable(kullanarak ApplicationRunner)
  3. Gradle ve Eclipse

adımlar

Çalışması için aşağıdaki adımları izlemem gerekiyordu

  1. @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false)Aramalarınızdan üzerine yerleştirilmek üzere Beanelle örneklenemez etmektir. Benim durumumda, Beanmanuel olarak örneklenecek olan @Autowiredhizmetlere sahip olduğundan, yukarıdaki açıklamaya destek.
  2. Spring Boot'un ana bölümüne XXXApplicaiton.java(veya ile açıklama eklenen dosyaya @SpringBootApplication) @EnableSpringConfiguredve ile açıklama ekleyin.@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
  3. Bağımlılıkları derleme dosyanıza ekleyin (yani, hangisini kullandığınıza bağlı olarak build.gradle veya pom.xml) compile('org.springframework.boot:spring-boot-starter-aop')vecompile('org.springframework:spring-aspects:5.0.7.RELEASE')
  4. Yeni + Beanup'ınız, @Configurableherhangi bir yerde ek açıklamalı ve bağımlılıkları otomatik olarak kablolanmalıdır.

* Yukarıdaki 3. maddeyle ilgili olarak , org.springframework.boot:spring-boot-starter-aopgeçişli spring-aopolarak (burada gösterildiği gibi mavencentral ) çektiğinin farkındayım, ancak benim durumumda Eclipse @EnableSpringConfiguredek açıklamaları çözemedi, bu nedenle spring-aopbaşlatıcıya ek olarak bağımlılığı neden açıkça ekledim . Aynı sorunla karşılaşırsanız, bağımlılığı ilan edin veya çözme macerasına çıkın.

  • Sürüm çakışması var mı
  • Neden org.springframework.context.annotation.aspect.*mevcut değil
  • IDE kurulumunuz doğru mu
  • Vs vs.
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.