Auto-configuration — Bu Bean Nereden Geldi?
Önce şunu oku: IoC ve Dependency Injection
30 saniyede özet
Spring Boot sihir yapmaz, bir kontrol listesine bakar: şu kütüphane var mı, şu ayar yazılmış mı, sen zaten kendi nesneni tanımladın mı? Eksik olanı kurar, seninkini gördüğünde geri çekilir.
İyi bir otelde odana girdiğinde ihtiyacın olan her şey hazırdır. Ama kendi ütünü getirdiysen, otel bir ütü daha koymaz.
-
Bayt: Projeye tek bir bağımlılık ekledim, bir satır ayar bile yazmadım.
-
Sen: Ve?
-
Bayt: Bir DataSource, bir EntityManagerFactory ve bir JdbcTemplate ortaya çıktı! Kim yazdı bunları?
-
Bayt: Sihir yok, bir kontrol listesi var. Resepsiyona bir bakalım.
Projeye tek bir bağımlılık ekledin ve uygulama artık bir veritabanı istiyor. Tek satır ayar yazmadın, ama bir DataSource, bir EntityManagerFactory ve bir JdbcTemplate ortaya çıktı. Nereden?
Starter getirir, auto-configuration kurar
Bir starterBir özellik için gereken bağımlılıkları tek paket hâlinde getiren boş bir modül. Kod içermez; asıl işi classpath'e düşen sınıflara bakan auto-configuration yapar.Sözlükte gör → bir alışveriş listesi gibidir: içinde neredeyse hiç kod yoktur, yalnızca gereken kütüphaneleri projeye getirir.
Asıl işi, @SpringBootApplication’ın içinde saklı @EnableAutoConfiguration yapar. Her kütüphane “ben şunları kurabilirim” diye bir aday listesi getirir; Boot her adayın koşuluna bakıp ya kurar ya geçer.
Bu adaylara auto-configurationSpring Boot'un classpath'e, ayarlara ve mevcut bean'lere bakarak senin yerine bean tanımlaması. Her tanım bir @Conditional koşuluna bağlıdır.Adaylar META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports dosyasında listelenir. Boot 3 ile spring.factories bu iş için artık okunmuyor.Sözlükte gör → denir. Her biri “şu varsa ve şu yoksa, şunu tanımla” diyen sıradan bir @Configuration sınıfıdır.
Kafam karıştı, daha basit anlat
Starter bir alışveriş listesidir, malzemeleri getirir. Auto-configuration ise aşçıdır: mutfakta ne olduğuna bakar ve ona göre yemeği hazırlar.
`spring-boot-starter-data-jpa` gibi bir starter'ın içinde ne vardır?
Spring Boot 3 hangi auto-configuration sınıflarının aday olduğunu nereden öğrenir?
Her bean bir koşula bağlı
| Koşul | Neye bakar | Örnek |
|---|---|---|
@ConditionalOnClass | Classpath | JDBC sınıfları varsa DataSource kur |
@ConditionalOnMissingBean | Kayıtlı bean’ler | Kullanıcı DataSource tanımlamadıysa |
@ConditionalOnProperty | Ayarlar | feature.x.enabled=true ise |
@ConditionalOnSingleCandidate | Kayıtlı bean’ler | Tek bir DataSource varsa JPA’yı kur |
Kendi @Bean DataSource metodunu yazdın. Boot da classpath'te JDBC görüyor. Kaç DataSource oluşur? Cevabı göster
Bir tane — seninki. Boot’un tanımı @ConditionalOnMissingBean(DataSource.class) ile işaretli ve senin bean’ini görünce vazgeçiyor.
Adım adım oku
- Boot her auto-configuration için bir kontrol listesine bakar.
- JDBC kütüphanesi classpath'te mi? Bağlantı adresi yazılmış mı? İkisi de evet.
- Senin tanımladığın bir DataSource yoksa Boot kendi DataSource'unu kurar.
- Sen @Bean ile yazdıysan Boot geri çekilir. İki durumda da uygulamada tek bir DataSource vardır.
Buna back offBir auto-configuration'ın, kullanıcı aynı işi gören bir bean tanımladığında kendi bean'ini oluşturmaktan vazgeçmesi. @ConditionalOnMissingBean ile sağlanır.Sözlükte gör → denir. Varsayılanı değiştirmek için exclude gerekmez; aynı tipte bir bean tanımlaman yeter.
Kafam karıştı, daha basit anlat
Kendi yemeğini getirdiysen aşçı aynısını pişirmez, kenara çekilir. Varsayılanı değiştirmek için kendi bean’ini tanımlaman yeter.
Uygulamada kendi `@Bean DataSource` metodunu tanımladın. Spring Boot'un DataSourceAutoConfiguration'ı ne yapar?
Her koşul anotasyonu neye bakar?
Kendin gör
Auto-configuration — bu bean nereden geldi?
Tohum 152291// build.gradleimplementation 'org.springframework.boot:spring-boot-starter-data-jpa'runtimeOnly 'org.postgresql:postgresql' # application.propertiesspring.datasource.url=jdbc:postgresql://db:5432/shop // Application.java@SpringBootApplication// kendi DataSource bean'i yok- DataSourceAutoConfiguration
- HibernateJpaAutoConfiguration
- JdbcTemplateAutoConfiguration
Şu an ne oldu?
SpringApplication.run() başladı
Önce senin @Configuration sınıfların işlenir, sonra auto-configuration adayları sırayla koşullarına göre değerlendirilir.
Görevler0/3
"'url' attribute is not specified" hatasını alaçık
İpucu
Boot bir DataSource kurmaya çalışsın ama ne bir adres ne de gömülü bir veritabanı bulsun.
Tek satır ayar yazmadan veritabanıyla ayağa kalkaçık
İpucu
url verme. Classpath'te gömülü bir veritabanı olursa Boot onu kendisi açar.
Kendi DataSource'unla Boot'unkini geri çektiraçık
İpucu
Aynı tipte bir bean tanımla; exclude kullanma.
Olay günlüğü (0)
Henüz olay yok. Oynat veya adımla.
- Varsayılanla oynat. Starter, sürücü ve url var: Hikari havuzu, JPA ve JdbcTemplate kuruldu.
- url’i kapat. Meşhur hata: “‘url’ attribute is not specified”.
- Sürücüyü H2 yap. Aynı durumda Boot bellek içi bir veritabanı açıyor.
- Kendi DataSource’unu aç. Boot’unki geri çekildi.
- Onu kapat ve exclude’u aç. DataSource yok, JPA kurulamıyor.
Projeye spring-boot-starter-data-jpa ve PostgreSQL sürücüsünü ekledin ama hiçbir ayar yazmadın. Uygulama başlarken ne olur?
Satır satır: bir auto-configuration okumak
Koşullar sırayla değerlendiriliyor
@AutoConfiguration@ConditionalOnClass(GreetingService.class)@EnableConfigurationProperties(GreetingProperties.class)public class GreetingAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnProperty(name = "greeting.enabled", matchIfMissing = true) GreetingService greetingService(GreetingProperties props) { return new GreetingService(props.prefix()); }}Debug
Boot Sınıf AutoConfiguration.imports dosyasında listelendiği için aday. Kullanıcının kendi yapılandırması çoktan işlendi.
Sol/sağ ok tuşlarıyla da gezebilirsin.
Bir bean’in nereden geldiğini tahmin etme, sor. Uygulamayı --debug ile başlat: CONDITIONS EVALUATION REPORT her adayın hangi koşulda eşleşip eşleşmediğini yazar.
Kafam karıştı, daha basit anlat
Her @Conditional... satırı bir “eğer”dir: bu sınıf varsa, bu bean yoksa, bu ayar açıksa. Hepsi evet derse bean kurulur.
Bir bean'in neden oluşturulmadığını ya da nereden geldiğini görmenin en doğrudan yolu hangisi?
Tuzaklar
Kendi starter'ını yazarken· istersen atla
Auto-configuration sınıfını uygulamanın taradığı pakete koyma: sıra garantisi kaybolur ve @ConditionalOnMissingBean yanlış karar verir. Boot 3’ten beri kayıt yalnızca AutoConfiguration.imports dosyasından okunur, spring.factories artık yetmez.
Düşünmeden exclude. Tek bir bean’i değiştirmek istiyorsan kendininkini tanımlaman yeter. exclude, o auto-configuration’ın getirdiği her şeyi birden kapatır.
Gereksiz starter. Classpath’e düşen her kütüphane yeni auto-configuration’ları tetikleyebilir. Kullanmadığın starter’ı kaldır.
Şirket içi bir kütüphanede varsayılan bir CacheManager sunmak istiyorsun, kullanıcı kendi CacheManager'ını tanımlarsa geri çekilmeli. Bazı servislerde iki CacheManager oluşuyor. Hangi satırlar sorunlu?
Bankalarda her serviste denetim kaydı zorunludur; platform ekibi bunu tek bağımlılıkla kuran bir starter yazar. Aşağıdaki örnek böyle bir starter: koşullar, ödeme servisinin kendi sink’iyle geri çekilme ve testleri.
Derinleş · Bankanın platform ekibinden: audit-spring-boot-starter 6 dosya · ~87 satır · ilk okumada atlayabilirsin
Kendini sına
Bir starter içinde çoğunlukla kod değil, bağımlılık listesi vardır.
Spring dokümantasyonu @ConditionalOnMissingBean'i yalnızca auto-configuration sınıflarında kullanmayı önerir. Neden?
Aklında kalacak üç şey
- 1 Starter kod getirmez, bağımlılık getirir. Nesneleri kuran şey, ortama bakıp karar veren auto-configuration sınıflarıdır.
- 2 Aynı tipte kendi bean'ini tanımladığında Boot'unki geri çekilir. exclude ise o auto-configuration'ı tamamen kapatır.
- 3 Bir bean'in neden kurulduğunu ya da kurulmadığını --debug ile açılan koşul raporu söyler.
5 kart sonraki derste seni bekliyor
Bu dersin üstüne kurulanlar
Bunlar bu dersi temel alıyor; hazır olduğunda devam edebilirsin.
- Spring Boot EkosistemiActuator ve Gözlemlenebilirlik — Sağlık, Metrik, İzUygulaman yaşıyorum diyor ama hiç istek alamıyor. Hangi soruyu yanlış cevapladı?Derse git
- Spring Boot EkosistemiKonfigürasyon ve Profiller — Bu Değer Nereden Geldi?Aynı ayar üç farklı yerde yazıyor. Hangisi kazanır?Derse git
- Spring Boot EkosistemiWAR ve Uygulama Sunucusu — Tomcat'te Çalışan, WildFly'da Neden Açılmadı?Rapor uygulaması yıllardır Tomcat'te çalışıyordu. Aynı WAR'ı WildFly'a koydun; açılmadı. Sunucu neye itiraz etti?Derse git