Spring @Configuration sınıfını anlama


108

İlkbahar @ Otomatik Kablolu kullanımı Anlamak sorusunun ardından, diğer yaylı kablolama seçeneği olan @Configurationsınıf için eksiksiz bir bilgi tabanı oluşturmak istedim .

Şuna benzeyen bir yaylı XML dosyam olduğunu varsayalım:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <import resource="another-application-context.xml"/>

  <bean id="someBean" class="stack.overflow.spring.configuration.SomeClassImpl">
    <constructor-arg value="${some.interesting.property}" />
  </bean>

  <bean id="anotherBean" class="stack.overflow.spring.configuration.AnotherClassImpl">
    <constructor-arg ref="someBean"/>
    <constructor-arg ref="beanFromSomewhereElse"/>
  </bean>
</beans>

@ConfigurationBunun yerine nasıl kullanabilirim ? Kodun kendisi üzerinde herhangi bir etkisi var mı?

Yanıtlar:


151

XML şuraya taşınıyor: @Configuration

Xml'yi @Configurationbirkaç adımda geçirmek mümkündür :

  1. @ConfigurationEk açıklamalı bir sınıf oluşturun :

    @Configuration
    public class MyApplicationContext {
    
    }
  2. Her bir <bean>etiket için aşağıdakilerle açıklanmış bir yöntem oluşturun @Bean:

    @Configuration
    public class MyApplicationContext {
    
      @Bean(name = "someBean")
      public SomeClass getSomeClass() {
        return new SomeClassImpl(someInterestingProperty); // We still need to inject someInterestingProperty
      }
    
      @Bean(name = "anotherBean")
      public AnotherClass getAnotherClass() {
        return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse); // We still need to inject beanFromSomewhereElse
      }
    }
  3. İçe beanFromSomewhereElseaktarmak için tanımını içe aktarmamız gerekiyor. Bir XML'de tanımlanabilir ve biz kullanacağız @ImportResource:

    @ImportResource("another-application-context.xml")
    @Configuration
    public class MyApplicationContext {
      ...  
    }

    Fasulye başka bir @Configurationsınıfta tanımlanmışsa @Importek açıklamayı kullanabiliriz :

    @Import(OtherConfiguration.class)
    @Configuration
    public class MyApplicationContext {
      ...
    }
  4. Diğer XML'leri veya @Configurationsınıfları içe aktardıktan sonra , @Configurationsınıfa özel bir üye bildirerek, kendi bağlamımızda bildirdikleri çekirdekleri aşağıdaki gibi kullanabiliriz:

    @Autowired
    @Qualifier(value = "beanFromSomewhereElse")
    private final StrangeBean beanFromSomewhereElse;

    Veya doğrudan bu bağlıdır fasulye tanımlayan yöntemde parametre olarak kullanmak beanFromSomewhereElsekullanarak @Qualifier, aşağıdaki gibi:

    @Bean(name = "anotherBean")
    public AnotherClass getAnotherClass(@Qualifier (value = "beanFromSomewhereElse") final StrangeBean beanFromSomewhereElse) {
      return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse);
    }
  5. Özelliklerin içe aktarılması, fasulyeyi başka bir xml veya @Configurationsınıftan içe aktarmaya çok benzer . Kullanmak yerine aşağıdaki özellikleri @Qualifierkullanacağız @Value:

    @Autowired
    @Value("${some.interesting.property}")
    private final String someInterestingProperty;

    Bu, SpEL ifadeleri ile de kullanılabilir .

  6. Spring'in bu tür sınıfları fasulye kapları olarak ele almasına izin vermek için, bu etiketi bağlama koyarak bunu ana XML'imizde işaretlememiz gerekir:

    <context:annotation-config/>

    Artık, @Configurationbasit bir fasulye oluşturduğunuz gibi sınıfları içe aktarabilirsiniz :

    <bean class="some.package.MyApplicationContext"/>

    Yaylı XML'lerden tamamen kaçınmanın yolları vardır, ancak bunlar bu yanıtın kapsamında değildir. Cevabımı dayandırdığım blog yazımda bu seçeneklerden birini öğrenebilirsiniz .


Bu yöntemi kullanmanın avantajları ve dezavantajları

Temel olarak, gördüğüm birkaç avantaj nedeniyle, bu fasulye bildirim yöntemini XML kullanmaktan çok daha rahat buluyorum:

  1. Yazım@Configuration hataları - sınıflar derlenir ve yazım hataları derlemelere izin vermez
  2. Hızlı başarısız (derleme zamanı) - Bir bean enjekte etmeyi unutursanız, XML'lerde olduğu gibi çalışma zamanında değil derleme zamanında başarısız olursunuz
  3. IDE'de gezinmek daha kolay - bağımlılık ağacını anlamak için fasulye yapıcıları arasında.
  4. Yapılandırma başlangıcında kolayca hata ayıklamak mümkün

Dezavantajları gördüğüm kadar çok değil ama aklıma gelen birkaç tane var:

  1. Kötüye Kullanım - Kodun kötüye kullanılması XML'lerden daha kolaydır
  2. XML'lerle, derleme sırasında kullanılamayan ancak çalışma zamanı sırasında sağlanan sınıflara göre bağımlılıkları tanımlayabilirsiniz. İle @Configurationsınıfları derleme zamanında mevcut sınıfları olmalıdır. Genellikle bu bir sorun değildir, ancak olabilecek durumlar vardır.

Sonuç olarak: XML'leri @Configurationve ek açıklamaları uygulamanızın bağlamında birleştirmek mükemmeldir . Bahar, bir fasulyenin ilan edildiği yöntemle ilgilenmez.


2
Olası dezavantajlardan biri, konfigürasyon kaybıdır. Diyelim ki geliştirmede bazı işlevlerle alay eden bir sınıfınız var, sonra onu UAT ortamında başka bir sınıfla değiştirmek istiyorsunuz. XML kullanmak, sadece yapılandırmayı değiştirmek ve uygulamanın çalışmasına / yeniden başlatılmasına izin vermek meselesidir. Bu yeni sınıf yapılandırmalarıyla, sınıfların yeniden derlenmesi gerekecektir.
Jose

5
@JoseChavez - Bu, birkaç kez duyduğum harika bir argüman. Ve XML'leri kavanozlarının / savaşlarının dışında kullanan herhangi bir uygulama veya sistem bulamadığım bazı istatistik araştırmaları yapmaya çalıştım. Bunun pratik anlamı, ya kavanozu açmanız ve XML'i değiştirmeniz (ki bunu yapan kimseyi bulamadım) ya da kavanozlarınızı yeniden oluşturmanız (ki konuştuğum herkesin şimdiye kadar yaptığını söylediği şey buydu). . Sonuç olarak, önemli bir argüman olabileceğinden, genellikle gerçek hayatta önemli değildir.
Avi

6
@ Profil ek açıklaması ve "$ {env.value}" sözdizimi bunun içindir. @Profile ("someName") ile, tüm konfigürasyonu yalnızca profil etkinken kullanılmak üzere etiketleyebilirsiniz. Application.properties (veya .yml) dosyanızda, daha sonra spring.profiles.active = birAdı, varsayılan ... ayarlayabilirsiniz ... Ortam değişkenlerine göre dinamik olarak ayarlamak için, yay değeri olarak $ {SOME_ENV_VAR} sözdizimini kullanın. active.profiles ve ortam değişkenini ayarlayın. Bahar artık java yapılandırmasının kullanılmasını öneriyor - docs.spring.io/spring-boot/docs/current/reference/htmlsingle/…
Jack Viers

Her bir çekirdeği yapılandırma dosyasında yöntem olarak tanımlamanın alternatifi nedir?
Asif Mushtaq

@AsifMushtaq - Otomatik tarama özelliğini kullanabilirsiniz ve bu @Component @Servicetür ek açıklamaları olan her sınıf otomatik olarak bir fasulyeye dönüştürülür (ancak bu sorunun odak noktası bu değildi)
Avi
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.