Configuration & Profiles

01.07.2026 | Muallif: Jaxongir a.k.a | Kategoriya: Spring Boot | 19 daqiqa o'qish

Configuration & profiles - Spring Boot application’ni turli muhitlarda boshqarish uchun ishlatiladi: local, development, test, production.

Bu bo‘lim ichida quyidagilar bor: @ConfigurationProperties, Spring Profiles, @Profile, spring.profiles.active, application-dev.yml, application-prod.yml, environment variables override.


1. Configuration nima?

Configuration - application sozlamalari.

Masalan:

server port
database URL
database username/password
JWT secret
file upload limit
logging level
external API URL
mail server config

Bularni kod ichiga qattiq yozish yomon.

Yomon:

String apiUrl = "https://api.example.com";
String dbPassword = "12345";

Yaxshi:

app:
  external-api-url: https://api.example.com

Keyin Java kodda config’dan o‘qiladi.


2. application.properties va application.yml

Spring Boot’da asosiy config fayl odatda:

src/main/resources/application.properties

yoki:

src/main/resources/application.yml

bo‘ladi.


application.properties

server.port=8080

spring.datasource.url=jdbc:postgresql://localhost:5432/shop_db
spring.datasource.username=postgres
spring.datasource.password=postgres

spring.jpa.hibernate.ddl-auto=validate

application.yml

server:
  port: 8080

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/shop_db
    username: postgres
    password: postgres

  jpa:
    hibernate:
      ddl-auto: validate

Ikkalasi ham ishlaydi. Lekin katta configlarda yml o‘qishga qulayroq.


3. Nega config kerak?

Config orqali application’ni kodni o‘zgartirmasdan boshqaramiz.

Masalan local’da database:

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/shop_db

Production’da esa:

spring:
  datasource:
    url: jdbc:postgresql://prod-db:5432/shop_db

Kod bir xil. Faqat config boshqa.


4. Profile nima?

Profile - application qaysi muhitda ishlayotganini bildiradigan nom.

Ko‘p ishlatiladigan profile’lar:

local
dev
test
staging
prod

Misol:

local → kompyuteringizda ishlaydi
dev → development server
test → test environment
prod → real userlar ishlatadigan production

5. Profile fayllar

Spring Boot profile bo‘yicha alohida config fayllarni o‘qiy oladi.

src/main/resources
 ├── application.yml
 ├── application-local.yml
 ├── application-dev.yml
 ├── application-test.yml
 └── application-prod.yml

Asosiy application.yml:

spring:
  application:
    name: shop-api

  profiles:
    active: local

application-local.yml:

server:
  port: 8080

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/shop_db
    username: postgres
    password: postgres

  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: true

application-prod.yml:

server:
  port: 8080

spring:
  datasource:
    url: ${DB_URL}
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}

  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false

Bu yerda production config’da password qattiq yozilmagan. Environment variable’dan olinadi.


6. spring.profiles.active

Qaysi profile ishlashini belgilaydi.

spring:
  profiles:
    active: dev

Yoki command line orqali:

java -jar app.jar --spring.profiles.active=prod

Yoki environment variable orqali:

SPRING_PROFILES_ACTIVE=prod

Real production’da ko‘pincha environment variable orqali beriladi.


7. Profile qanday ishlaydi?

Agar active profile:

spring:
  profiles:
    active: dev

bo‘lsa, Spring Boot quyidagilarni o‘qiydi:

application.yml
application-dev.yml

application-dev.yml ichidagi qiymatlar application.ymldagi umumiy qiymatlarni override qilishi mumkin.

Masalan:

application.yml:

server:
  port: 8080

application-dev.yml:

server:
  port: 8081

Natija:

server.port = 8081

8. @Value bilan config o‘qish

Eng oddiy usul - @Value.

application.yml:

app:
  upload-dir: uploads

Java:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class FileService {

    @Value("${app.upload-dir}")
    private String uploadDir;

    public void printUploadDir() {
        System.out.println(uploadDir);
    }
}

Bu ishlaydi, lekin katta configlar uchun uncha qulay emas.


@Value kamchiligi

Agar config ko‘p bo‘lsa:

@Value("${app.jwt.secret}")
private String secret;

@Value("${app.jwt.expiration-minutes}")
private Long expirationMinutes;

@Value("${app.jwt.issuer}")
private String issuer;

Kod tarqalib ketadi.

Shuning uchun @ConfigurationProperties yaxshiroq.


9. @ConfigurationProperties nima?

@ConfigurationProperties - config qiymatlarini bitta classga type-safe qilib yig‘ib beradi.

Masalan application.yml:

app:
  jwt:
    secret: my-secret-key
    expiration-minutes: 60
    issuer: shop-api

Config class:

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "app.jwt")
public record JwtProperties(
        String secret,
        Long expirationMinutes,
        String issuer
) {
}

Lekin bu classni Spring ro‘yxatdan o‘tkazish kerak.


10. @EnableConfigurationProperties

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(JwtProperties.class)
public class PropertiesConfig {
}

Endi JwtProperties bean bo‘ladi.

Service’da ishlatish:

import org.springframework.stereotype.Service;

@Service
public class JwtService {

    private final JwtProperties jwtProperties;

    public JwtService(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;
    }

    public void printConfig() {
        System.out.println(jwtProperties.issuer());
        System.out.println(jwtProperties.expirationMinutes());
    }
}

11. Mutable class bilan @ConfigurationProperties

Record o‘rniga oddiy class ham ishlatish mumkin.

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "app.file")
public class FileStorageProperties {

    private String uploadDir;
    private Long maxSizeMb;

    public String getUploadDir() {
        return uploadDir;
    }

    public void setUploadDir(String uploadDir) {
        this.uploadDir = uploadDir;
    }

    public Long getMaxSizeMb() {
        return maxSizeMb;
    }

    public void setMaxSizeMb(Long maxSizeMb) {
        this.maxSizeMb = maxSizeMb;
    }
}

application.yml:

app:
  file:
    upload-dir: uploads
    max-size-mb: 10

12. @ConfigurationProperties validation

Config ham noto‘g‘ri bo‘lishi mumkin.

Masalan JWT secret bo‘sh bo‘lsa, application start bo‘lmasin.

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@Validated
@ConfigurationProperties(prefix = "app.jwt")
public record JwtProperties(

        @NotBlank(message = "JWT secret majburiy")
        String secret,

        @Min(value = 1, message = "Expiration kamida 1 minut bo‘lishi kerak")
        Long expirationMinutes,

        @NotBlank(message = "Issuer majburiy")
        String issuer
) {
}

Agar config noto‘g‘ri bo‘lsa, application start vaqtida xato beradi.

Bu yaxshi. Chunki production’da noto‘g‘ri config bilan application ishga tushib ketmaydi.


13. Environment variable nima?

Environment variable - server yoki OS darajasida beriladigan qiymat.

Masalan Linux’da:

export DB_URL=jdbc:postgresql://prod-db:5432/shop_db
export DB_USERNAME=shop_user
export DB_PASSWORD=super-secret

Spring Boot config’da:

spring:
  datasource:
    url: ${DB_URL}
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}

Bu production uchun muhim.


14. Default value berish

Agar environment variable yo‘q bo‘lsa, default qiymat berish mumkin.

server:
  port: ${SERVER_PORT:8080}

Ma’nosi:

Agar SERVER_PORT bor bo‘lsa → shuni ol
Agar yo‘q bo‘lsa → 8080 ishlat

Yana:

app:
  file:
    upload-dir: ${UPLOAD_DIR:uploads}

15. Secretlarni config faylga yozmang

Yomon:

spring:
  datasource:
    password: my-production-password

app:
  jwt:
    secret: very-secret-key

Nega yomon?

Gitga tushib qoladi
Developerlar ko‘radi
Repository leak bo‘lsa, production secret ochiladi
Secretni almashtirish qiyinlashadi

Yaxshi:

spring:
  datasource:
    password: ${DB_PASSWORD}

app:
  jwt:
    secret: ${JWT_SECRET}

16. Local uchun .env ishlatish

Local development’da .env yoki IDE environment variables ishlatish mumkin.

Masalan .env:

DB_URL=jdbc:postgresql://localhost:5432/shop_db
DB_USERNAME=postgres
DB_PASSWORD=postgres
JWT_SECRET=local-secret-key

Lekin .env odatda Gitga qo‘shilmaydi.

.gitignore:

.env

17. @Profile nima?

@Profile - bean faqat ma’lum profile’da ishlashini bildiradi.

Masalan local profile’da test data yaratamiz:

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Component
@Profile("local")
public class LocalDataInitializer {

    public LocalDataInitializer() {
        System.out.println("Local data initializer ishladi");
    }
}

Bu bean faqat:

spring.profiles.active=local

bo‘lsa yaratiladi.


Prod’da boshqa bean

@Component
@Profile("prod")
public class ProdStartupLogger {

    public ProdStartupLogger() {
        System.out.println("Production mode");
    }
}

Bu faqat production profile’da ishlaydi.


18. @Profile bilan interface implementation tanlash

Masalan payment service local’da fake ishlasin, prod’da real ishlasin.

Interface:

public interface PaymentGateway {
    void pay(BigDecimal amount);
}

Local implementation:

@Service
@Profile("local")
public class FakePaymentGateway implements PaymentGateway {

    @Override
    public void pay(BigDecimal amount) {
        System.out.println("Fake payment: " + amount);
    }
}

Production implementation:

@Service
@Profile("prod")
public class RealPaymentGateway implements PaymentGateway {

    @Override
    public void pay(BigDecimal amount) {
        // real payment provider call
    }
}

Service:

@Service
public class OrderService {

    private final PaymentGateway paymentGateway;

    public OrderService(PaymentGateway paymentGateway) {
        this.paymentGateway = paymentGateway;
    }
}

Agar active profile local bo‘lsa, FakePaymentGateway inject bo‘ladi.

Agar prod bo‘lsa, RealPaymentGateway inject bo‘ladi.


19. Profile expression

@Profile ichida expression ham yozish mumkin.

@Profile("!prod")

Ma’nosi:

prod bo‘lmagan hamma profile’da ishlaydi

Misol:

@Component
@Profile("!prod")
public class DebugLogger {
}

Yoki:

@Profile("dev | local")

Ma’nosi:

dev yoki local bo‘lsa ishlaydi

20. Logging config

Local’da SQL va debug log ko‘proq kerak.

application-local.yml:

logging:
  level:
    root: INFO
    org.hibernate.SQL: DEBUG
    org.hibernate.orm.jdbc.bind: TRACE

Production’da kamroq:

logging:
  level:
    root: INFO
    org.hibernate.SQL: WARN

Yomon amaliyot:

logging:
  level:
    root: TRACE

Production’da haddan tashqari ko‘p log performance va xavfsizlik muammo qiladi.


21. Profile bo‘yicha database config

application-local.yml:

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/shop_db
    username: postgres
    password: postgres

application-dev.yml:

spring:
  datasource:
    url: jdbc:postgresql://dev-db:5432/shop_db
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}

application-prod.yml:

spring:
  datasource:
    url: ${DB_URL}
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}

Farq:

local → oddiy lokal config bo‘lishi mumkin
dev/prod → secretlar env orqali

22. Product API uchun config misol

application.yml:

spring:
  application:
    name: shop-api

  profiles:
    active: local

app:
  pagination:
    default-page-size: 20
    max-page-size: 100

application-local.yml:

server:
  port: 8080

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/shop_db
    username: postgres
    password: postgres

  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: true

  flyway:
    enabled: true
    locations: classpath:db/migration

application-prod.yml:

server:
  port: ${SERVER_PORT:8080}

spring:
  datasource:
    url: ${DB_URL}
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}

  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false

  flyway:
    enabled: true
    locations: classpath:db/migration

app:
  pagination:
    default-page-size: ${DEFAULT_PAGE_SIZE:20}
    max-page-size: ${MAX_PAGE_SIZE:100}

23. Pagination config’ni classga chiqarish

application.yml:

app:
  pagination:
    default-page-size: 20
    max-page-size: 100

Properties class:

import jakarta.validation.constraints.Min;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@Validated
@ConfigurationProperties(prefix = "app.pagination")
public record PaginationProperties(

        @Min(1)
        int defaultPageSize,

        @Min(1)
        int maxPageSize
) {
}

Config registration:

@Configuration
@EnableConfigurationProperties(PaginationProperties.class)
public class AppPropertiesConfig {
}

Service’da ishlatish:

@Service
public class ProductService {

    private final PaginationProperties paginationProperties;

    public ProductService(PaginationProperties paginationProperties) {
        this.paginationProperties = paginationProperties;
    }

    public Page<ProductResponse> getAll(Integer page, Integer size) {
        int finalPage = page == null ? 0 : page;
        int finalSize = size == null
                ? paginationProperties.defaultPageSize()
                : Math.min(size, paginationProperties.maxPageSize());

        Pageable pageable = PageRequest.of(finalPage, finalSize);

        // repository call
        return Page.empty(pageable);
    }
}

24. Config priority: qaysi biri ustun?

Spring Boot’da config manbalari ko‘p bo‘lishi mumkin:

application.yml
application-prod.yml
environment variables
command line arguments

Amaliy jihatdan eslab qolish:

Command line argument ko‘pincha yuqoriroq priority
Environment variable ham file configni override qila oladi
Profile-specific file umumiy application.yml ustidan yozadi

Masalan:

application.yml:

server:
  port: 8080

Run command:

java -jar app.jar --server.port=9090

Natija:

server.port = 9090

25. Docker bilan profile ishlatish

Docker run:

docker run \
  -e SPRING_PROFILES_ACTIVE=prod \
  -e DB_URL=jdbc:postgresql://db:5432/shop_db \
  -e DB_USERNAME=shop_user \
  -e DB_PASSWORD=secret \
  -p 8080:8080 \
  shop-api:latest

Docker Compose:

services:
  app:
    image: shop-api:latest
    ports:
      - "8080:8080"
    environment:
      SPRING_PROFILES_ACTIVE: prod
      DB_URL: jdbc:postgresql://db:5432/shop_db
      DB_USERNAME: shop_user
      DB_PASSWORD: secret

26. Test profile

Testlar uchun alohida profile foydali.

application-test.yml:

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    username: sa
    password:

  jpa:
    hibernate:
      ddl-auto: create-drop

Test class:

@SpringBootTest
@ActiveProfiles("test")
class ProductServiceTest {
}

Bu test paytida application-test.yml ishlatadi.


27. @ActiveProfiles

@ActiveProfiles testlarda profile tanlash uchun ishlatiladi.

@SpringBootTest
@ActiveProfiles("test")
class ProductControllerTest {
}

Bu test environment’ni production configdan ajratadi.

Muhim:

Test hech qachon production databasega ulanmasligi kerak.

28. Configuration class nima?

Ba’zan beanlarni alohida config classda e’lon qilamiz.

@Configuration
public class AppConfig {

    @Bean
    public Clock clock() {
        return Clock.systemUTC();
    }
}

Endi Clock kerak bo‘lgan joyda inject qilinadi:

@Service
public class TimeService {

    private final Clock clock;

    public TimeService(Clock clock) {
        this.clock = clock;
    }
}

Profile bilan:

@Configuration
@Profile("test")
public class TestConfig {

    @Bean
    public Clock fixedClock() {
        return Clock.fixed(
                Instant.parse("2026-01-01T00:00:00Z"),
                ZoneOffset.UTC
        );
    }
}

29. Ko‘p uchraydigan xatolar

Xato 1: Production secretni Gitga yozish

Yomon:

spring:
  datasource:
    password: real-prod-password

To‘g‘ri:

spring:
  datasource:
    password: ${DB_PASSWORD}

Xato 2: prod profile’da show-sql: true

Yomon:

spring:
  jpa:
    show-sql: true

Production’da keraksiz SQL loglar chiqadi.


Xato 3: ddl-auto=updateni prod’da qoldirish

Yomon:

spring:
  jpa:
    hibernate:
      ddl-auto: update

Yaxshi:

spring:
  jpa:
    hibernate:
      ddl-auto: validate

Xato 4: Hamma configni @Value bilan tarqatib yuborish

Yomon:

@Value("${app.jwt.secret}")
private String secret;

@Value("${app.jwt.expiration-minutes}")
private Long expiration;

Katta config uchun yaxshiroq:

@ConfigurationProperties(prefix = "app.jwt")
public record JwtProperties(...) {}

Xato 5: Active profile’ni kodga qattiq bog‘lash

Yomon:

spring:
  profiles:
    active: prod

Buni production jar ichida qoldirish xavfli. Serverda environment variable orqali berish yaxshiroq:

SPRING_PROFILES_ACTIVE=prod

30. Java developer uchun qisqa qoida

application.yml → umumiy config
application-local.yml → lokal muhit
application-dev.yml → dev server
application-prod.yml → production
spring.profiles.active → qaysi profile ishlashini tanlaydi
@Profile → bean faqat ma’lum profile’da yaratiladi
@Value → oddiy bitta qiymat uchun
@ConfigurationProperties → katta/type-safe config uchun
Environment variables → secret va server-specific config uchun

31. Amaliy vazifa

Oldingi Product CRUD API loyihasiga profile va config qo‘shing.

Fayllar

src/main/resources/application.yml
src/main/resources/application-local.yml
src/main/resources/application-prod.yml

application.yml

spring:
  application:
    name: shop-api

  profiles:
    active: local

app:
  pagination:
    default-page-size: 20
    max-page-size: 100

  jwt:
    secret: ${JWT_SECRET:local-secret}
    expiration-minutes: ${JWT_EXPIRATION_MINUTES:60}
    issuer: shop-api

application-local.yml

server:
  port: 8080

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/shop_db
    username: postgres
    password: postgres

  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: true

  flyway:
    enabled: true

application-prod.yml

server:
  port: ${SERVER_PORT:8080}

spring:
  datasource:
    url: ${DB_URL}
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}

  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false

  flyway:
    enabled: true

Properties classlar

PaginationProperties
JwtProperties
AppPropertiesConfig

Talablar

JWT secret @ConfigurationProperties orqali o‘qilsin
Pagination max size configdan olinsin
Prod secretlar environment variable orqali berilsin
Testlarda @ActiveProfiles("test") ishlatilsin

Xulosa

Configuration & profiles real Spring Boot application’ni professional boshqarish uchun kerak.

Eng muhim fikr:

Kod o‘zgarmaydi.
Config muhitga qarab o‘zgaradi.

Java developer quyidagilarni bilishi kerak:

application.yml
application-{profile}.yml
spring.profiles.active
@Profile
@Value
@ConfigurationProperties
@EnableConfigurationProperties
environment variables
default values: ${VAR:default}
local/dev/prod config ajratish
secretlarni Gitga yozmaslik