Spring Boot Yapılandırmasını Özelleştirme: Auto-Configuration Override
Spring Boot; otomatik yapılandırma, starter bağımlılıklar ve gömülü sunucu sayesinde hızlı başlangıç sağlar. Ancak her uygulama “tek beden” değildir. Bu rehberde, auto-configuration’u gerektiğinde nasıl devre dışı bırakıp özelleştireceğinizi, dış yapılandırmayla (properties/YAML) ince ayar yapmayı, profillerle ortam ayrımı yapmayı ve özel hata sayfası tasarlamayı öğreneceksiniz.
- Auto-Configuration Nedir? Ne Zaman Geçersiz Kılınır?
- Örnek: Spring Security’yi Manuel Olarak Özelleştirmek
- Koşullu Yapılandırma:
@ConditionalOnMissingBeanve Arkası - Dış Yapılandırma: application.properties & YAML
- İnce Ayar Örnekleri: Thymeleaf Cache, Port, HTTPS, Logging
- Veritabanı / DataSource Yapılandırması ve Havuzlama
- Kendi Bean’lerinize Dışarıdan Değer Enjekte Etmek
- Profiller ile Ortam Bazlı Yapılandırma
- Özel Hata Sayfası (Whitelabel’ın Yerine)
- Hızlı Kontrol Listesi & En İyi Uygulamalar
1) Auto-Configuration Nedir? Ne Zaman Geçersiz Kılınır?
Spring Boot, classpath’te gördüğü kütüphanelere ve mevcut bean’lere bakarak “koşullu” yapılandırma uygular. Bu sayede; web, veri erişimi, şablon motorları, güvenlik ve daha onlarca alan için sıfır çabayla başlangıç yaparsınız. Kolaylık Hız Koşullu Yapılandırma
Ancak bazı durumlarda (özellikle güvenlik, loglama, veritabanı gibi konularda) auto-configuration’un “en iyi tahmini” size uymayabilir. Böyle bir durumda Spring Boot, uygulamanızın kendi yapılandırmasına öncelik verir; yani siz manuel bir bean veya config yazdığınızda otomatik olanını saygıyla geri çeker.
2) Örnek: Spring Security’yi Manuel Olarak Özelleştirmek
spring-boot-starter-security eklendiğinde varsayılan olarak HTTP Basic Authentication gelir; kullanıcı adı user,
parola ise her çalıştırmada log’a üretilir. Bu, gerçek projelerde çoğu zaman yeterli değildir. Kendi login sayfanızı ve doğrulama mantığınızı tanımlayın.
2.1. Güvenlik Starter’ı Ekle
implementation "org.springframework.boot:spring-boot-starter-security"
2.2. WebSecurityConfigurerAdapter ile Özelleştir
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ReaderRepository readerRepository;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").hasRole("READER")
.antMatchers("/**").permitAll()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error=true");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(username -> readerRepository.findOne(username));
}
}
Üstteki yapılandırma, / istekleri için READER rolü ister, diğer tüm istekleri serbest bırakır, özel bir login sayfası kullanır ve kullanıcıları JPA üzerinden doğrular.
2.3. UserDetails Tabanlı Varlık
@Entity
public class Reader implements UserDetails {
@Id
private String username;
private String fullname;
private String password;
@Override public Collection<? extends GrantedAuthority> getAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority("READER"));
}
@Override public boolean isAccountNonExpired() { return true; }
@Override public boolean isAccountNonLocked() { return true; }
@Override public boolean isCredentialsNonExpired() { return true; }
@Override public boolean isEnabled() { return true; }
// getter/setter
}
Bu yaklaşımda Spring Security, doğrudan JPA varlığınızı kullanıcı olarak kullanır. Basit örnek için idealdir.
3) Koşullu Yapılandırma: @ConditionalOnMissingBean ve Arkası
Auto-configuration sınıfları, Spring 4 ile gelen “koşullu yapılandırma” desteğini kullanır. Önemli taşlardan biri
@ConditionalOnMissingBean’dir: eğer aynı tipte bir bean zaten uygulama tarafından sağlanmışsa, auto-configuration o bean’i yaratmaz.
@Bean
@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(this.dataSource);
}
Benzer şekilde SpringBootWebSecurityConfiguration, WebSecurityConfiguration tipi bir bean bulunursa devreye girmez.
Siz @EnableWebSecurity kullandığınızda bu koşul sağlanır ve kendi güvenlik config’iniz öne geçer.
4) Dış Yapılandırma: application.properties & application.yml
Spring Boot, 300+ özelliği dışarıdan ayarlamanıza izin verir: komut satırı, JNDI, sistem özellikleri, ortam değişkenleri,
application.properties ve application.yml. Öncelik sırası en üstte komut satırı olacak şekilde düzenlenmiştir.
- Komut satırı argümanları
- JNDI (java:comp/env)
- JVM sistem özellikleri
- Ortam değişkenleri
- application.properties / application.yml (dış → iç)
- @PropertySource
- Varsayılanlar
./config/dizini (dış)- Uygulamanın çalıştığı kök dizin (dış)
classpath:config/(iç)classpath:/kök (iç)
Aynı seviyede hem properties hem YAML varsa, YAML değerleri properties’i geçersiz kılar.
5) İnce Ayar Örnekleri
5.1. Thymeleaf Cache’i Kapama (Geliştirme için)
spring.thymeleaf.cache=false
Freemarker, Groovy Templates, Velocity için de benzer spring.*.cache anahtarları mevcuttur.
5.2. Gömülü Sunucu Portu
server.port=8000
Birden fazla uygulamayı aynı makinede çalıştırırken port çakışmalarını önler.
5.3. HTTPS Etkinleştirme
$ keytool -keystore mykeys.jks -genkey -alias tomcat -keyalg RSA
server:
port: 8443
ssl:
key-store: classpath:mykeys.jks
key-store-password: letmein
key-password: letmein
Geliştirme sırasında tarayıcı güven uyarısı görebilirsiniz; localhost için normaldir.
5.4. Logging Seviyeleri ve Dosyaya Yazma
logging:
level:
root: WARN
org.springframework.security: DEBUG
path: /var/logs/
file: BookWorm.log
Varsayılan logback yapılandırmasını tamamen özelleştirmek isterseniz logback.xml ekleyebilirsiniz.
6) DataSource & Bağlantı Havuzu
Üretimde gömülü H2 yerine kalıcı bir veritabanı kullanacaksanız yalnızca URL ve kimlik bilgilerini tanımlamanız çoğu zaman yeterlidir.
Sürücüyü genellikle URL’den otomatik algılar. Aksi halde driver-class-name belirtin.
spring:
datasource:
url: jdbc:mysql://localhost/readinglist
username: dbuser
password: dbpass
# driver-class-name: com.mysql.jdbc.Driver
Spring Boot; Tomcat JDBC pool’u varsa onu, yoksa HikariCP, Commons DBCP veya DBCP2 gibi havuzları classpath’e göre kullanır. İsterseniz kendi DataSource bean’inizi manuel tanımlayarak farklı bir pool da seçebilirsiniz.
spring.datasource.jndi-name=java:/comp/env/jdbc/readingListDS tanımı yapılırsa URL/kullanıcı/parola yok sayılır.7) Kendi Bean’lerinize Dışarıdan Değer Enjekte Etmek
“Magic string” ve gizli değerleri (ör. affiliate ID, API anahtarı) şablonlara veya koda gömmek yerine dış yapılandırmadan enjekte edin.
7.1. @ConfigurationProperties ile Toplamak
@Component
@ConfigurationProperties("amazon")
public class AmazonProperties {
private String associateId;
public String getAssociateId() { return associateId; }
public void setAssociateId(String associateId) { this.associateId = associateId; }
}
amazon:
associateId: habuma-20
7.2. Controller’da Kullanmak
@Controller
@RequestMapping("/")
public class ReadingListController {
private final ReadingListRepository repo;
private final AmazonProperties amazon;
public ReadingListController(ReadingListRepository repo, AmazonProperties amazon) {
this.repo = repo;
this.amazon = amazon;
}
@GetMapping
public String readersBooks(Reader reader, Model model) {
List<Book> readingList = repo.findByReader(reader);
if (readingList != null) {
model.addAttribute("books", readingList);
model.addAttribute("reader", reader);
model.addAttribute("amazonID", amazon.getAssociateId());
}
return "readingList";
}
}
Properties adlandırmada associateId, associate-id ve associate_id eşdeğerdir. Dilediğinizi kullanabilirsiniz.
8) Profiller ile Ortam Bazlı Yapılandırma
Geliştirme, test ve üretimde farklı ayarlar gereklidir. Spring profiles ile bunu temizce yönetebilirsiniz. Aktif profili:
$ java -jar app.jar --spring.profiles.active=production
veya
spring:
profiles:
active: production
Properties tarafında application-{profile}.properties / YAML tarafında application-{profile}.yml kullanabilirsiniz. Tek dosyada çoklu profil de mümkündür.
8.1. Tek YAML Dosyada Çoklu Profil
logging:
level:
root: INFO
---
spring:
profiles: development
logging:
level:
root: DEBUG
---
spring:
profiles: production
logging:
path: /tmp/
file: BookWorm.log
level:
root: WARN
9) Özel Hata Sayfası (Whitelabel’ın Yerine)
Spring Boot varsayılan “Whitelabel Error Page” ile gelir (bkz. Sayfa 72). Projenize uygun, kullanıcı dostu bir
hata sayfası için error.html isimli bir şablon koymanız yeterlidir. Şablonda path, message, status, timestamp gibi
öznitelikler otomatik sağlanır.
<!-- src/main/resources/templates/error.html -->
<html>
<head><title>Oops!</title></head>
<body>
<div class="errorPage">
<h1>Oops! Bir hata oluştu.</h1>
<p>İstek yolu: <span th:text="${path}"></span></p>
<p th:text="${'Detay: ' + message}"></p>
</div>
</body>
</html>
src/main/resources/static veya public altına yerleştirin.10) Hızlı Kontrol Listesi & En İyi Uygulamalar
- Önce auto-configuration’dan yararlanın, gerekirse manuel bean tanımlayın. (
@ConditionalOnMissingBean) - Tüm ayarları dışarıdan yönetin; kodda sabit değer bırakmayın. (
application.ymlönerilir) - Geliştirmede
spring.thymeleaf.cache=false, üretimde açık kalsın. - Port/HTTPS/log seviyelerini properties ile yönetin; profillerle ortam bazlı değiştirin.
- DataSource için yalnızca URL/kullanıcı/parola girin; havuz seçimini Spring Boot’a bırakın veya istediğiniz pool’u manuel tanımlayın.
- Whitelabel yerine markalı bir
error.htmlekleyin; kullanıcıya nazik mesajlar gösterin.