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 boshqaradi3. 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
@ConfigurationFarqi nima?
Annotation | Ma’nosi |
|---|---|
| Umumiy Spring bean |
| Business logic class |
| DB bilan ishlaydigan class |
| MVC controller |
| REST API controller |
| 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;
finalishlatish 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?
finalishlatib 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 |
|---|---|
| Spring context ichida bitta instance |
| Har so‘ralganda yangi instance |
| Har HTTP request uchun bitta |
| 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:
ApplicationRunnerCommandLineRunnerApplicationReadyEventmigration 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 method9. 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 ServiceMasalan, 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 rollbackBu 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:
RuntimeExceptionError
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 |
|---|---|
| Mavjud transaction bo‘lsa unga qo‘shiladi, bo‘lmasa yangi ochadi |
| Har doim yangi transaction ochadi |
| Transaction bo‘lishi shart |
| Bo‘lsa ishlatadi, bo‘lmasa transactionsiz |
| 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 |
|---|---|
| Commit bo‘lmagan data ham ko‘rinishi mumkin |
| Faqat commit bo‘lgan data ko‘rinadi |
| Bir transaction ichida qayta o‘qilganda data o‘zgarmaydi |
| 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 |
|---|---|
| null bo‘lmasin |
| null, bo‘sh, space bo‘lmasin |
| collection/string bo‘sh bo‘lmasin |
| email format |
| minimal son |
| maksimal son |
| uzunlik yoki collection size |
| regex |
| musbat son |
| o‘tgan sana |
| 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
PaymentSucceededEventEvent 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
prodFilelar:
application.yml
application-dev.yml
application-prod.ymlapplication.yml
spring:
profiles:
active: devapplication-dev.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/app_devapplication-prod.yml
spring:
datasource:
url: jdbc:postgresql://prod-db:5432/appIshga tushirish:
java -jar app.jar --spring.profiles.active=prodYoki environment variable:
SPRING_PROFILES_ACTIVE=prod28. @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: 5sProperties 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/passwordSystem 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‘radiSpring’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 = 123456Yaxshi:
@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‘yadiHeader:
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 etadi38. CORS va CSRF
CORS
Frontend boshqa domain’dan backend’ga request yuborsa CORS kerak bo‘ladi.
Masalan:
frontend: https://app.uz
backend: https://api.uzCORS 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/loggers40. Actuator config
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: when_authorizedPublic qilish mumkin bo‘lgan endpoint:
/actuator/healthLekin quyidagilarni public ochish xavfli:
/actuator/env
/actuator/beans
/actuator/configpropsChunki 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/prometheus42. 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
└── facade45. 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
AnalyticsService3. @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;
@Transactionalrollback 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 qilinadiEng muhim 4 ta joy:
1. Dependency Injection
2. AOP / Proxy
3. Transaction Management
4. Security + Validation + Actuator