Spring Framework chuqurlashtirilgan

30.06.2026 | Muallif: Jaxongir a.k.a | Kategoriya: Spring Boot | 31 daqiqa o'qish

Javada Spring Framework Deep Dive ichiga quyidagilar kiradi: Spring AOP & proxies, Transaction management, Spring Security basics, Spring Validation, Spring Events, Profiles & environment configuration, Spring Actuator & metrics.

Bu bosqichda Spring Boot’da faqat Controller → Service → Repository yozish yetmaydi. Endi Spring ichida nima bo‘layotganini tushunish kerak.


1. Spring Framework nima?

Spring Framework - Java backend application yaratish uchun katta ekotizim.

Spring quyidagilarni beradi:

Yo‘nalish

Vazifasi

IoC Container

Objectlarni yaratadi va boshqaradi

Dependency Injection

Class dependency’larini ulab beradi

AOP

Method atrofiga qo‘shimcha logic qo‘shadi

Transaction

DB operatsiyalarni boshqaradi

Security

Authentication va authorization

Validation

Request ma’lumotlarini tekshiradi

Events

Ichki eventlar bilan ishlash

Actuator

Production monitoring


2. IoC - Inversion of Control

Oddiy Java’da objectni o‘zimiz yaratamiz:

UserRepository repository = new UserRepository();
UserService service = new UserService(repository);

Spring’da esa objectni Spring yaratadi:

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

Bu yerda UserRepositoryni biz yaratmadik. Spring container yaratib berdi.

IoC nima degani?

Control bizing qo‘limizdan Spring container’ga o‘tadi.

Ya’ni:

Oldin:
Developer object yaratadi

Spring’da:
Spring object yaratadi, ulaydi, lifecycle’ni boshqaradi

3. Bean nima?

Bean - Spring container boshqaradigan object.

Masalan:

@Service
public class UserService {
}

Bu class Spring bean bo‘ladi.

Boshqa annotationlar ham bean yaratadi:

@Component
@Service
@Repository
@Controller
@RestController
@Configuration

Farqi nima?

Annotation

Ma’nosi

@Component

Umumiy Spring bean

@Service

Business logic class

@Repository

DB bilan ishlaydigan class

@Controller

MVC controller

@RestController

REST API controller

@Configuration

Config class

Texnik jihatdan @Service, @Repository, @Controller ham @Componentning maxsus turlari.


4. Dependency Injection

Dependency Injection - kerakli dependency’ni class ichida new qilmasdan tashqaridan olish.

Yomon variant

@Service
public class OrderService {

    private final PaymentService paymentService = new PaymentService();
}

Muammo:

  • test qilish qiyin;

  • mock qilish qiyin;

  • classlar kuchli bog‘lanib qoladi;

  • Spring lifecycle ishlamaydi.

Yaxshi variant

@Service
public class OrderService {

    private final PaymentService paymentService;

    public OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
}

Bu constructor injection.


5. Constructor Injection nima uchun yaxshi?

Constructor injection afzalliklari:

  • dependency majburiy bo‘ladi;

  • final ishlatish mumkin;

  • test qilish oson;

  • circular dependency tezroq bilinadi;

  • object to‘liq holatda yaratiladi.

@Service
public class OrderService {

    private final OrderRepository orderRepository;
    private final PaymentService paymentService;

    public OrderService(
            OrderRepository orderRepository,
            PaymentService paymentService
    ) {
        this.orderRepository = orderRepository;
        this.paymentService = paymentService;
    }
}

Field injection’dan qochish kerak

Yomon:

@Autowired
private OrderRepository orderRepository;

Nega yomon?

  • final ishlatib bo‘lmaydi;

  • testda object yaratish qiyin;

  • dependency yashirin;

  • null xavfi bor.


6. Bean Scope

Spring bean har doim ham bitta bo‘lavermaydi. Scope mavjud.

Scope

Ma’nosi

singleton

Spring context ichida bitta instance

prototype

Har so‘ralganda yangi instance

request

Har HTTP request uchun bitta

session

Har HTTP session uchun bitta

Default scope - singleton.

@Service
public class UserService {
}

Bu Spring context ichida bitta object.

Singleton bean’da state saqlash xavfli

Yomon:

@Service
public class UserService {

    private Long currentUserId;

    public void setCurrentUserId(Long currentUserId) {
        this.currentUserId = currentUserId;
    }
}

Ko‘p request bir vaqtda kelsa, currentUserId aralashib ketadi.

Yaxshi:

public UserDto getUser(Long currentUserId) {
    return findById(currentUserId);
}

State’ni method argument yoki local variable sifatida ishlat.


7. Bean Lifecycle

Spring bean hayoti soddalashtirib:

1. Class topiladi
2. Bean definition yaratiladi
3. Object yaratiladi
4. Dependency injection bo‘ladi
5. BeanPostProcessor ishlaydi
6. @PostConstruct ishlaydi
7. Bean foydalanishga tayyor
8. App yopilganda @PreDestroy ishlaydi

@PostConstruct

@PostConstruct
public void init() {
    System.out.println("Bean tayyor bo‘ldi");
}

Lekin ehtiyot bo‘lish kerak.

@PostConstruct ichida quyidagilarni qilmaslik yaxshi:

  • og‘ir DB query;

  • tashqi HTTP call;

  • cache warmup;

  • uzoq davom etadigan task;

  • boshqa beanlar hali to‘liq tayyor bo‘lmasdan murakkab logic.

Yaxshiroq variantlar:

  • ApplicationRunner

  • CommandLineRunner

  • ApplicationReadyEvent

  • migration uchun Flyway/Liquibase

  • scheduled/background job


8. Spring AOP

AOP - Aspect-Oriented Programming.

Asosiy business logicga aralashtirmasdan qo‘shimcha logic qo‘shadi.

Masalan:

  • logging;

  • transaction;

  • security;

  • cache;

  • metrics;

  • audit.

Oddiy business method

public OrderDto createOrder(CreateOrderRequest request) {
    // business logic
}

AOP orqali Spring method atrofida qo‘shimcha ish qiladi:

before method
methodni bajar
after method

9. Aspect misol

Custom annotation:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
}

Aspect:

@Aspect
@Component
public class ExecutionTimeAspect {

    @Around("@annotation(LogExecutionTime)")
    public Object measure(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();

        try {
            return joinPoint.proceed();
        } finally {
            long duration = System.currentTimeMillis() - start;
            System.out.println(joinPoint.getSignature() + " took " + duration + " ms");
        }
    }
}

Ishlatish:

@LogExecutionTime
public OrderDto createOrder(CreateOrderRequest request) {
    return doCreate(request);
}

10. Proxy nima?

Spring AOP ko‘pincha proxy orqali ishlaydi.

Client → Proxy → Real Service

Masalan, biz buni yozamiz:

@Transactional
public void createOrder() {
    // db logic
}

Spring esa taxminan shunday qiladi:

transaction boshlash
createOrder() chaqirish
xato bo‘lmasa commit
xato bo‘lsa rollback

Bu ishni proxy bajaradi.


11. JDK Proxy vs CGLIB Proxy

Spring proxy odatda ikki xil bo‘ladi:

Proxy turi

Qachon ishlaydi

JDK Dynamic Proxy

Interface asosida

CGLIB Proxy

Classni subclass qilib

JDK proxy

public interface PaymentService {
    void pay();
}

Spring interface orqali proxy qila oladi.

CGLIB proxy

Agar interface yo‘q bo‘lsa, Spring classdan subclass yaratadi.

@Service
public class PaymentService {
    public void pay() {}
}

12. Self-invocation muammosi

Bu juda muhim.

@Service
public class OrderService {

    public void outer() {
        inner();
    }

    @Transactional
    public void inner() {
        // transaction kutilyapti
    }
}

outer() ichidan inner() chaqirilsa, proxy ishlamay qolishi mumkin. Chunki chaqiruv object ichida bo‘lyapti.

Tashqaridan chaqirilsa:
Client → Proxy → inner()

Ichkaridan chaqirilsa:
this.inner()

this.inner() proxy’dan o‘tmaydi.

Yechim

Transactional methodni boshqa servicega chiqarish:

@Service
public class OrderTransactionService {

    @Transactional
    public void inner() {
        // transaction ishlaydi
    }
}
@Service
public class OrderService {

    private final OrderTransactionService transactionService;

    public OrderService(OrderTransactionService transactionService) {
        this.transactionService = transactionService;
    }

    public void outer() {
        transactionService.inner();
    }
}

13. Transaction Management

@Transactional - DB operatsiyalarni bitta transaction ichida bajaradi.

@Transactional
public void transfer(Long fromId, Long toId, BigDecimal amount) {
    accountService.withdraw(fromId, amount);
    accountService.deposit(toId, amount);
}

Agar deposit() joyida xato chiqsa, withdraw() ham rollback bo‘ladi.


14. Transaction qachon kerak?

Quyidagi holatlarda kerak:

  • bir nechta DB update bitta birlik bo‘lsa;

  • order yaratish + order item yaratish;

  • pul yechish + pul tushirish;

  • status update + audit log;

  • stock kamaytirish + order yaratish.

Misol:

@Transactional
public OrderDto createOrder(CreateOrderRequest request) {
    Order order = orderRepository.save(new Order());

    for (OrderItemRequest item : request.items()) {
        orderItemRepository.save(new OrderItem(order, item.productId()));
    }

    return OrderDto.from(order);
}

Agar itemlardan birida xato bo‘lsa, order ham rollback bo‘ladi.


15. Rollback qachon bo‘ladi?

Default holatda Spring quyidagilarda rollback qiladi:

  • RuntimeException

  • Error

Lekin checked exception’da rollback bo‘lmasligi mumkin.

@Transactional
public void process() throws IOException {
    throw new IOException("File error");
}

Bu holatda rollback kerak bo‘lsa:

@Transactional(rollbackFor = IOException.class)
public void process() throws IOException {
    throw new IOException("File error");
}

16. Propagation

Propagation - mavjud transaction bo‘lsa, yangi method unga qanday munosabatda bo‘lishini belgilaydi.

Eng ko‘p ishlatiladiganlari:

Propagation

Ma’nosi

REQUIRED

Mavjud transaction bo‘lsa unga qo‘shiladi, bo‘lmasa yangi ochadi

REQUIRES_NEW

Har doim yangi transaction ochadi

MANDATORY

Transaction bo‘lishi shart

SUPPORTS

Bo‘lsa ishlatadi, bo‘lmasa transactionsiz

NOT_SUPPORTED

Transactionsiz ishlaydi

Default - REQUIRED.

REQUIRES_NEW misol

Audit logni asosiy transaction rollback bo‘lsa ham saqlamoqchimiz.

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveAuditLog(String message) {
    auditRepository.save(new AuditLog(message));
}

Lekin ehtiyot bo‘lish kerak. REQUIRES_NEW noto‘g‘ri ishlatilsa connection pool muammosi chiqarishi mumkin.


17. Isolation

Isolation - transactionlar bir-birini qanday ko‘rishini belgilaydi.

Isolation

Ma’nosi

READ_UNCOMMITTED

Commit bo‘lmagan data ham ko‘rinishi mumkin

READ_COMMITTED

Faqat commit bo‘lgan data ko‘rinadi

REPEATABLE_READ

Bir transaction ichida qayta o‘qilganda data o‘zgarmaydi

SERIALIZABLE

Eng qat’iy, lekin sekinroq

Ko‘p DBlarda odatiy holatda READ_COMMITTED yoki REPEATABLE_READ ishlatiladi.

Misol

@Transactional(isolation = Isolation.READ_COMMITTED)
public OrderDto getOrder(Long id) {
    return repository.findById(id).map(OrderDto::from).orElseThrow();
}

Isolation’ni ko‘r-ko‘rona oshirish yomon. Lock ko‘payishi va performance pasayishi mumkin.


18. readOnly = true

Faqat o‘qish uchun:

@Transactional(readOnly = true)
public List<UserDto> getUsers() {
    return userRepository.findAll()
            .stream()
            .map(UserDto::from)
            .toList();
}

Bu Hibernate va DB optimizatsiyasiga yordam berishi mumkin.

Lekin readOnly = true hamma DBda "mutlaqo yozmaydi" degani emas. Uni performance hint sifatida tushunish kerak.


19. @Transactional qayerga qo‘yiladi?

Odatda service layerga.

Yaxshi:

@Service
public class OrderService {

    @Transactional
    public OrderDto createOrder(CreateOrderRequest request) {
        // business + db operations
    }
}

Yomonroq:

@RestController
public class OrderController {

    @Transactional
    @PostMapping("/orders")
    public OrderDto create(@RequestBody CreateOrderRequest request) {
        // controller ichida transaction
    }
}

Controller HTTP bilan ishlasin. Transaction business use case atrofida bo‘lsin.


20. Spring Validation

Validation - request data’ni tekshirish.

Dependency odatda:

implementation("org.springframework.boot:spring-boot-starter-validation")

DTO:

public record CreateUserRequest(
        @NotBlank(message = "Name bo‘sh bo‘lmasin")
        String name,

        @Email(message = "Email noto‘g‘ri")
        String email,

        @Min(value = 18, message = "Yosh kamida 18 bo‘lishi kerak")
        int age
) {
}

Controller:

@PostMapping("/users")
public ResponseEntity<UserDto> create(@Valid @RequestBody CreateUserRequest request) {
    return ResponseEntity.ok(userService.create(request));
}

Agar request noto‘g‘ri bo‘lsa, Spring validation error tashlaydi.


21. Validation annotationlar

Annotation

Vazifasi

@NotNull

null bo‘lmasin

@NotBlank

null, bo‘sh, space bo‘lmasin

@NotEmpty

collection/string bo‘sh bo‘lmasin

@Email

email format

@Min

minimal son

@Max

maksimal son

@Size

uzunlik yoki collection size

@Pattern

regex

@Positive

musbat son

@Past

o‘tgan sana

@Future

kelajak sana


22. Global Exception Handler

Validation errorni chiroyli JSON qilib qaytarish kerak.

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidation(
            MethodArgumentNotValidException ex
    ) {
        List<FieldErrorResponse> errors = ex.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(error -> new FieldErrorResponse(
                        error.getField(),
                        error.getDefaultMessage()
                ))
                .toList();

        return ResponseEntity.badRequest()
                .body(new ErrorResponse("VALIDATION_ERROR", errors));
    }
}

DTO:

public record ErrorResponse(
        String code,
        List<FieldErrorResponse> errors
) {
}
public record FieldErrorResponse(
        String field,
        String message
) {
}

Response:

{
  "code": "VALIDATION_ERROR",
  "errors": [
    {
      "field": "email",
      "message": "Email noto‘g‘ri"
    }
  ]
}

23. Custom Validator

Masalan, phone number faqat Uzbekistan formatida bo‘lsin.

Annotation:

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UzbekPhoneValidator.class)
public @interface UzbekPhone {
    String message() default "Telefon raqam noto‘g‘ri";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Validator:

public class UzbekPhoneValidator implements ConstraintValidator<UzbekPhone, String> {

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) {
            return false;
        }

        return value.matches("^\\+998\\d{9}$");
    }
}

Ishlatish:

public record RegisterRequest(
        @UzbekPhone
        String phone
) {
}

24. Spring Events

Spring Events - application ichida event publish/listen qilish.

Masalan:

OrderCreatedEvent
UserRegisteredEvent
PaymentSucceededEvent

Event yaratish

public record OrderCreatedEvent(Long orderId) {
}

Publish qilish

@Service
public class OrderService {

    private final ApplicationEventPublisher eventPublisher;

    public OrderService(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    @Transactional
    public OrderDto createOrder(CreateOrderRequest request) {
        Order order = orderRepository.save(new Order());

        eventPublisher.publishEvent(new OrderCreatedEvent(order.getId()));

        return OrderDto.from(order);
    }
}

Listen qilish

@Component
public class OrderNotificationListener {

    @EventListener
    public void handle(OrderCreatedEvent event) {
        System.out.println("Order created: " + event.orderId());
    }
}

25. @TransactionalEventListener

Agar event transaction commit bo‘lgandan keyin ishlashi kerak bo‘lsa:

@Component
public class OrderNotificationListener {

    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handle(OrderCreatedEvent event) {
        System.out.println("Commitdan keyin notification yuboriladi");
    }
}

Bu juda foydali.

Masalan:

  • order DBga commit bo‘lgandan keyin SMS yuborish;

  • payment success bo‘lgandan keyin email;

  • user ro‘yxatdan o‘tgandan keyin welcome notification.

Aks holda transaction rollback bo‘lsa ham SMS ketib qolishi mumkin.


26. Async Event

Listener’ni async qilish mumkin:

@Async
@EventListener
public void handle(OrderCreatedEvent event) {
    // background thread
}

Buning uchun:

@EnableAsync
@Configuration
public class AsyncConfig {
}

Production’da custom executor sozlash kerak:

@Bean
public Executor applicationTaskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(10);
    executor.setMaxPoolSize(50);
    executor.setQueueCapacity(100);
    executor.setThreadNamePrefix("app-async-");
    executor.initialize();
    return executor;
}

27. Profiles

Profile - har xil environment uchun config ajratish.

Masalan:

dev
test
staging
prod

Filelar:

application.yml
application-dev.yml
application-prod.yml

application.yml

spring:
  profiles:
    active: dev

application-dev.yml

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

application-prod.yml

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

Ishga tushirish:

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

Yoki environment variable:

SPRING_PROFILES_ACTIVE=prod

28. @Profile

Ayrim bean faqat bitta profile’da ishlasin:

@Component
@Profile("dev")
public class DevDataSeeder implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) {
        System.out.println("Dev data seeding");
    }
}

Bu class faqat dev profile’da ishlaydi.


29. Configuration Properties

Configlarni type-safe qilish uchun.

YAML:

payment:
  payme:
    merchant-id: "123"
    timeout: 5s

Properties class:

@ConfigurationProperties(prefix = "payment.payme")
public record PaymeProperties(
        String merchantId,
        Duration timeout
) {
}

Enable qilish:

@EnableConfigurationProperties(PaymeProperties.class)
@Configuration
public class PaymentConfig {
}

Ishlatish:

@Service
public class PaymeClient {

    private final PaymeProperties properties;

    public PaymeClient(PaymeProperties properties) {
        this.properties = properties;
    }
}

Bu @Valuedan ko‘ra tozaroq.


30. @Value qachon?

Oddiy bitta qiymat uchun ishlatsa bo‘ladi:

@Value("${app.name}")
private String appName;

Lekin ko‘p config bo‘lsa, @ConfigurationProperties yaxshi.


31. Spring Security Basics

Spring Security ikki asosiy savolga javob beradi:

Tushuncha

Savol

Authentication

Siz kimsiz?

Authorization

Sizga nima mumkin?


32. Authentication

User login qiladi:

phone/password yoki username/password

System tekshiradi:

password to‘g‘rimi?
user active’mi?

Agar to‘g‘ri bo‘lsa, token beriladi.


33. Authorization

User login qilgandan keyin unga ruxsat tekshiriladi.

Masalan:

ADMIN → hamma narsani ko‘radi
MANAGER → orderlarni ko‘radi
USER → faqat o‘z orderlarini ko‘radi

Spring’da:

@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin/users")
public List<UserDto> getUsers() {
    return userService.getUsers();
}

34. SecurityFilterChain

Spring Security config:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
                .csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/api/auth/**").permitAll()
                        .requestMatchers("/actuator/health").permitAll()
                        .anyRequest().authenticated()
                )
                .build();
    }
}

35. PasswordEncoder

Parolni plain text saqlash mutlaqo noto‘g‘ri.

Yomon:

password = 123456

Yaxshi:

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

Ishlatish:

String encoded = passwordEncoder.encode(rawPassword);
boolean matches = passwordEncoder.matches(rawPassword, encoded);

36. JWT flow

Oddiy JWT flow:

1. User login qiladi
2. Server username/password tekshiradi
3. JWT token beradi
4. Client har requestda token yuboradi
5. Server tokenni tekshiradi
6. SecurityContext ichiga userni qo‘yadi

Header:

Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

37. JWT filter g‘oyasi

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain
    ) throws ServletException, IOException {

        String token = extractToken(request);

        if (token != null && isValid(token)) {
            Authentication authentication = buildAuthentication(token);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        filterChain.doFilter(request, response);
    }
}

Bu yerda asosiy g‘oya:

request keladi
token olinadi
token validatsiya qilinadi
authentication yaratiladi
SecurityContextga yoziladi
request davom etadi

38. CORS va CSRF

CORS

Frontend boshqa domain’dan backend’ga request yuborsa CORS kerak bo‘ladi.

Masalan:

frontend: https://app.uz
backend: https://api.uz

CORS config kerak.

CSRF

Session-cookie asosidagi browser app’larda muhim.

Agar stateless JWT API bo‘lsa, odatda CSRF disable qilinadi:

csrf(csrf -> csrf.disable())

Lekin har doim contextga qarab qaror qilish kerak.


39. Actuator

Spring Boot Actuator production monitoring uchun endpointlar beradi.

Dependency:

implementation("org.springframework.boot:spring-boot-starter-actuator")

Endpointlar:

/actuator/health
/actuator/info
/actuator/metrics
/actuator/prometheus
/actuator/env
/actuator/loggers

40. Actuator config

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  endpoint:
    health:
      show-details: when_authorized

Public qilish mumkin bo‘lgan endpoint:

/actuator/health

Lekin quyidagilarni public ochish xavfli:

/actuator/env
/actuator/beans
/actuator/configprops

Chunki sensitive configlar chiqib ketishi mumkin.


41. Metrics

Metrics - app ishlashi bo‘yicha raqamlar.

Masalan:

  • request count;

  • request duration;

  • JVM memory;

  • GC pause;

  • thread count;

  • DB connection pool;

  • HTTP status count.

Micrometer orqali Prometheus’ga chiqarish mumkin.

Dependency:

implementation("io.micrometer:micrometer-registry-prometheus")

Endpoint:

/actuator/prometheus

42. Custom Metric

@Component
public class OrderMetrics {

    private final Counter orderCreatedCounter;

    public OrderMetrics(MeterRegistry meterRegistry) {
        this.orderCreatedCounter = Counter.builder("orders.created")
                .description("Created orders count")
                .register(meterRegistry);
    }

    public void incrementCreatedOrders() {
        orderCreatedCounter.increment();
    }
}

Ishlatish:

orderMetrics.incrementCreatedOrders();

43. Health Indicator

Custom health check:

@Component
public class PaymentHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        boolean paymentOk = checkPaymentProvider();

        if (paymentOk) {
            return Health.up().build();
        }

        return Health.down()
                .withDetail("payment", "Provider unavailable")
                .build();
    }

    private boolean checkPaymentProvider() {
        return true;
    }
}

44. Real production structure

Middle-level Spring Boot projectda taxminan shunday structure yaxshi:

src/main/java/uz/example/order
 ├── config
 ├── controller
 ├── dto
 │    ├── request
 │    └── response
 ├── entity
 ├── enums
 ├── exception
 ├── mapper
 ├── repository
 ├── security
 ├── service
 ├── event
 ├── listener
 ├── client
 └── facade

45. Layer vazifalari

Layer

Vazifasi

Controller

HTTP request/response

Service

Business logic

Repository

DB access

Entity

DB model

DTO

API request/response

Mapper

Entity ↔ DTO

Client

External API

Config

Bean/configuration

Security

Auth logic

Event/Listener

Internal events

Facade

Use case orchestration


46. Ko‘p uchraydigan xatolar

1. Controller ichida business logic

Yomon:

@PostMapping("/orders")
public OrderDto create(@RequestBody CreateOrderRequest request) {
    // validation
    // db save
    // payment
    // sms
    // response mapping
}

Yaxshi:

@PostMapping("/orders")
public OrderDto create(@Valid @RequestBody CreateOrderRequest request) {
    return orderService.create(request);
}

2. Service ichida hamma narsani qilish

Yomon:

OrderService {
    createOrder()
    pay()
    sendSms()
    generateInvoice()
    updateAnalytics()
}

Yaxshi:

OrderService
PaymentService
NotificationService
InvoiceService
AnalyticsService

3. @Transactionalni noto‘g‘ri joyga qo‘yish

Yomon:

@Transactional
public void sendSms() {
    smsClient.send();
}

SMS tashqi API. Uni DB transaction ichida ushlab turish ko‘pincha yomon.

Yaxshi:

@Transactional
public Order createOrder() {
    return orderRepository.save(order);
}

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void sendSms(OrderCreatedEvent event) {
    smsClient.send();
}

4. @Async bilan transactionni aralashtirish

@Transactional
public void createOrder() {
    Order order = repository.save(order);
    asyncService.send(order.getId());
}

Agar async method transaction commit bo‘lmasdan ishlasa, DBdan order topilmasligi mumkin.

Yaxshi:

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
@Async
public void handle(OrderCreatedEvent event) {
    sendNotification(event.orderId());
}

5. Configlarni hardcode qilish

Yomon:

String url = "https://payme.uz/api";

Yaxshi:

payment:
  payme:
    url: https://payme.uz/api
@ConfigurationProperties(prefix = "payment.payme")
public record PaymeProperties(String url) {
}

47. Interview savollari

IoC nima?

Object yaratish va dependency boshqarish nazorati frameworkga berilishi.

Bean nima?

Spring container boshqaradigan object.

@Component, @Service, @Repository farqi?

Hammasi bean yaratadi. Lekin semantic ma’nosi farq qiladi. @Repository DB exception translation imkoniyatlariga ham bog‘liq.

Constructor injection nima uchun yaxshi?

Dependency majburiy, test qilish oson, final ishlatish mumkin.

Spring AOP qanday ishlaydi?

Ko‘pincha proxy orqali. Method chaqiruvini o‘rab, logging/transaction/security kabi logic qo‘shadi.

@Transactional qanday ishlaydi?

Proxy methoddan oldin transaction ochadi, method tugaganda commit qiladi, exception bo‘lsa rollback qiladi.

Self-invocation nima?

Bitta class ichida method boshqa annotated methodni chaqirsa, proxy chetlab o‘tiladi. Shuning uchun @Transactional, @Async, @Cacheable ishlamasligi mumkin.

REQUIRED va REQUIRES_NEW farqi?

REQUIRED mavjud transactionga qo‘shiladi.
REQUIRES_NEW yangi transaction ochadi.

@EventListener va @TransactionalEventListener farqi?

@EventListener event publish bo‘lishi bilan ishlaydi.
@TransactionalEventListener transaction phase’ga bog‘lab ishlaydi, masalan AFTER_COMMIT.

Actuator nima?

Production monitoring va management endpointlari to‘plami.


48. Java Developer checklist

Spring Framework Deep Dive bo‘yicha biz quyidagilarni bilishimiz kerak:

  • IoC va DI qanday ishlaydi;

  • bean nima;

  • bean scope;

  • bean lifecycle;

  • constructor injection;

  • AOP va proxy;

  • self-invocation muammosi;

  • @Transactional rollback qoidalari;

  • propagation va isolation;

  • Spring Validation;

  • Global Exception Handler;

  • Spring Events;

  • @TransactionalEventListener;

  • profiles va config management;

  • @ConfigurationProperties;

  • Spring Security asoslari;

  • JWT flow;

  • Actuator va metrics;

  • production’da endpointlarni xavfsiz ochish.


Qisqa xulosa

Spring Deep Dive - Spring Boot’da "CRUD yozish"dan keyingi bosqich.

Java developer quyidagilarni tushunishi kerak:

Spring objectlarni qanday yaratadi
Proxylar qanday ishlaydi
Transaction qachon commit/rollback bo‘ladi
Security requestni qanday tekshiradi
Validation error qanday qaytariladi
Eventlar transaction bilan qanday ishlaydi
Production monitoring qanday qilinadi

Eng muhim 4 ta joy:

1. Dependency Injection
2. AOP / Proxy
3. Transaction Management
4. Security + Validation + Actuator