150 adet ileri seviye soru ve cevapla hazırlanmış kapsamlı arşiv
Spring Boot ve Hibernate mülakatlarında en çok sorulan konular
@Transactional anotasyonu ile ilgili mülakat soruları ve cevapları
25 adet ileri seviye mikroservis sorusu ve cevabı
25 adet ileri seviye Spring Batch sorusu ve cevabı
25 adet ileri seviye Spring Caching sorusu ve cevabı
25 adet ileri seviye Spring AOP & Events sorusu ve cevabı
25 adet ileri seviye Spring Integration sorusu ve cevabı
25 adet ileri seviye Spring DevOps sorusu ve cevabı
Bu dokümanda Spring Boot & Hibernate mülakatlarında en çok sorulan konular soru-cevap mantığıyla açıklanmış ve örnek kodlar eklenmiştir.
Cevap: `@Transactional`, Spring'in transaction yönetimi için kullanılan bir anotasyondur.
Örnek:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void registerUser(User user) {
userRepository.save(user);
if(user.getEmail() == null) {
throw new RuntimeException("Email cannot be null!");
}
}
}
Cevap:
Örnek:
@Transactional(propagation = Propagation.REQUIRES_NEW,
isolation = Isolation.REPEATABLE_READ,
rollbackFor = Exception.class,
timeout = 5)
public void processOrder(Order order) { ... }
Soru: `@OneToOne`, `@OneToMany`, `@ManyToOne`, `@ManyToMany` ilişkilerini açıklayın.
Cevap:
@Entity
public class User {
@OneToOne(cascade = CascadeType.ALL)
private Address address;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Order> orders;
}
Soru: `FetchType.LAZY` ve `FetchType.EAGER` arasındaki fark nedir?
Cevap:
Örnek:
@OneToMany(fetch = FetchType.LAZY) private List<Order> orders;
Soru: N+1 select problemi nedir? Hibernate'de nasıl çözülür?
Cevap: N+1 problemi, ilişkili verileri çekerken her bir kayıt için ayrı bir sorgu çalıştırılmasıdır.
Çözüm:
@Query("SELECT u FROM User u JOIN FETCH u.orders")
List<User> findAllWithOrders();
Soru: Hibernate'de 1st level cache ve 2nd level cache farkı nedir?
Cevap:
Örnek:
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User { ... }
Soru: Optimistic ve Pessimistic Locking nedir?
Cevap:
Örnek:
@Version private Long version; // Optimistic Locking // Pessimistic Locking User user = entityManager.find(User.class, 1L, LockModeType.PESSIMISTIC_WRITE);
Soru: Derived Query, JPQL, Native Query farkı nedir?
Cevap:
Örnek:
// Derived Query
User findByEmail(String email);
// JPQL
@Query("SELECT u FROM User u WHERE u.email = ?1")
User findByEmailJPQL(String email);
// Native Query
@Query(value = "SELECT * FROM users WHERE email = ?1", nativeQuery = true)
User findByEmailNative(String email);
Soru: Dirty Read, Non-Repeatable Read, Phantom Read nedir?
Cevap:
Örnek:
@Transactional(isolation = Isolation.SERIALIZABLE)
public void updateBalance(...) { ... }
Soru: `@SpringBootApplication` altında hangi anotasyonlar vardır?
Cevap:
Soru: Spring Boot'ta global exception handling nasıl yapılır?
Cevap:
Örnek:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handle(RuntimeException ex) {
return ResponseEntity.badRequest().body(ex.getMessage());
}
}
Soru: AOP nedir? Hangi use-case'lerde kullanılır?
Cevap:
Örnek:
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore() {
System.out.println("Method çağrılmadan önce loglandı");
}
}
Soru: JWT Authentication nasıl çalışır?
Cevap:
Örnek:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.csrf().disable()
.authorizeHttpRequests()
.requestMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
.and()
.build();
}
Bu doküman Spring Boot & Hibernate mülakatlarında en sık karşılaşılan konuları soru-cevap ve kod örnekleri ile açıklamaktadır.
Bu döküman, Spring Boot ve Hibernate projelerinde sıklıkla sorulan `@Transactional` anotasyonu ile ilgili mülakat sorularını, açıklamalarını ve kod örneklerini kapsamlı olarak içermektedir.
Cevap:
Örnek Kod:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void createUserAndAccount(User user, Account account) {
userRepository.save(user);
if (account.getBalance() < 0) {
throw new RuntimeException("Hatalı bakiye!");
}
}
}
Transaction yayılım davranışını belirler. Varsayılan:
Propagation.REQUIRED
| Propagation Tipi | Açıklama |
|---|---|
| REQUIRED | Mevcut transaction varsa onu kullanır, yoksa yeni açar. |
| REQUIRES_NEW | Her zaman yeni transaction açar. Mevcut varsa askıya alır. |
| MANDATORY | Transaction yoksa exception fırlatır. |
| SUPPORTS | Transaction varsa kullanır, yoksa transaction olmadan çalışır. |
| NOT_SUPPORTED | Transaction varsa askıya alır, işlemi transaction olmadan yapar. |
| NEVER | Transaction olmadan çalışır, eğer varsa exception atar. |
| NESTED | Mevcut transaction içinde nested transaction açar. |
Örnek Kod:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog(Log log) {
logRepository.save(log);
}
Transaction izolasyon seviyesini belirler. Kirli okuma, tekrar eden okuma ve phantom read problemlerini kontrol eder.
| Isolation Seviyesi | Açıklama |
|---|---|
| DEFAULT | DB'nin varsayılan ayarını kullanır. |
| READ_UNCOMMITTED | Kirli okumalara izin verir. |
| READ_COMMITTED | Sadece commit edilmiş verileri okur. |
| REPEATABLE_READ | Transaction boyunca aynı satırı hep aynı görür. |
| SERIALIZABLE | En yüksek seviye, tüm transaction'lar sırayla çalışır. |
Örnek Kod:
@Transactional(isolation = Isolation.SERIALIZABLE)
public void transferMoney(Long fromId, Long toId, double amount) {
// En katı izolasyon seviyesi ile çalışır
}
rollbackFor: Belirtilen exception oluşursa rollback yapılır.
noRollbackFor: Belirtilen exception oluşursa rollback yapılmaz.
Örnek Kod:
@Transactional(rollbackFor = {IOException.class, SQLException.class})
public void riskyOperation() throws IOException {
// IOException veya SQLException olursa rollback olur
}
@Transactional(noRollbackFor = IllegalArgumentException.class)
public void safeOperation() {
// IllegalArgumentException olursa rollback olmaz
}
Transaction maksimum çalışma süresini (saniye cinsinden) belirler. Süre aşılırsa rollback yapılır.
Örnek Kod:
@Transactional(timeout = 5)
public void longRunningTask() {
// 5 saniyeyi geçerse rollback olur
}
Sorgunun sadece okuma amaçlı olduğunu belirtir. Hibernate dirty check yapmaz → performans artar.
Örnek Kod:
@Transactional(readOnly = true) public ListfindAllUsers() { return userRepository.findAll(); }
@Transactional → Transaction yönetimini sağlar.propagation, isolation,
timeout, readOnly, rollbackFor,
noRollbackFor.
Örnek Kod:
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private PaymentRepository paymentRepository;
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
public void placeOrder(Order order, Payment payment) {
orderRepository.save(order);
paymentRepository.save(payment);
if (payment.getAmount() <= 0) {
throw new RuntimeException("Ödeme hatalı!");
}
}
@Transactional(readOnly = true)
public List getAllOrders() {
return orderRepository.findAll();
}
}
Senior seviye mikroservis mimarisi mülakat soruları ve cevapları.
Mikroservisler birçok küçük servise bölündüğü için client doğrudan her servise çağrı yaparsa karmaşa çıkar. API Gateway tek giriş noktası sağlar, güvenlik, rate-limiting, logging, load balancing gibi işlemleri üstlenir.
Örnek: Spring Cloud Gateway kullanımı
spring:
cloud:
gateway:
routes:
- id: user-service
uri: http://localhost:8081
predicates:
- Path=/users/**
Servisler kendilerini discovery server'a register eder. Client'lar doğrudan IP bilmeden servislere ulaşır.
Kod örneği (Eureka Client):
@EnableEurekaClient
@SpringBootApplication
public class OrderServiceApp {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApp.class, args);
}
}
Bir servis çökerse, sürekli retry edip sistemi yormak yerine fallback çalıştırır. Netflix Hystrix / Resilience4j ile yapılır.
Kod örneği (Resilience4j):
@CircuitBreaker(name = "inventoryService", fallbackMethod = "fallback")
public String callInventory() {
return restTemplate.getForObject("http://inventory-service/stock", String.class);
}
public String fallback(Throwable t) {
return "Envanter servisi şu anda kullanılamıyor";
}
Servisler birbirini REST ile değil event/message broker (Kafka, RabbitMQ) üzerinden dinler. Loose coupling sağlar.
Kafka Listener örneği:
@KafkaListener(topics = "order-events", groupId = "payment-service")
public void consume(String message) {
System.out.println("Gelen event: " + message);
}
Dağıtık transaction yönetimi için kullanılır. Örn: Sipariş oluştur → ödeme al → stok düş → hata varsa roll-back için compensating action çalışır.
Mikroservislerde bir isteğin birden fazla servisi tetiklemesi sonucu sorunların kaynağı zor bulunur. Distributed tracing (Zipkin, Jaeger) ile tüm çağrılar takip edilir.
Örnek Konfigürasyon:
spring.zipkin.base-url=http://localhost:9411 spring.sleuth.sampler.probability=1
Trafik birden fazla servis instance'ı arasında dengelenir. Spring Cloud LoadBalancer veya Ribbon ile uygulanabilir.
WebClient ile Load Balancing:
@Autowired
private WebClient.Builder webClientBuilder;
public String getUser() {
return webClientBuilder.build()
.get()
.uri("http://user-service/users")
.retrieve()
.bodyToMono(String.class)
.block();
}
Tekrarlanan istekler sistem üzerinde hataya neden olmamalıdır. Örn: Sipariş servisi, aynı requestId ile tekrarlandığında sadece bir kez işlenir.
Read ve write operasyonlarının farklı veri modelleri ve performans gereksinimleri olduğunda tercih edilir.
State değişiklikleri event olarak saklanır. History ve audit işlemleri kolaylaşır.
Tüm config dosyaları merkezi bir server'da tutulur.
Örnek application.yml:
spring:
cloud:
config:
uri: http://localhost:8888
2PC (Two-Phase Commit), Saga pattern, veya Event Sourcing kullanılarak yönetilir.
URI versioning (/v1/users), header versioning (Accept-version: v1), veya parameter versioning (/users?version=v1) yöntemleri kullanılır.
OAuth2, JWT, veya API Gateway üzerinde merkezi kimlik doğrulama kullanılır.
Kubernetes, Docker Swarm, Apache Mesos gibi araçlarla container'lar yönetilir.
Prometheus, Grafana, ELK stack (Elasticsearch, Logstash, Kibana) ile monitoring yapılır.
ELK stack, Splunk, veya Fluentd ile loglar merkezi olarak toplanır.
Synchronous (REST, gRPC), Asynchronous (Message Queues), Event-driven communication pattern'leri kullanılır.
Her servisin kendi veritabanına sahip olması, servislerin birbirinden bağımsız çalışmasını sağlar.
Service mesh (Istio, Linkerd), servisler arası iletişimi yöneten, güvenlik, monitoring ve load balancing sağlayan bir altyapı katmanıdır.
İki aynı ortam (blue ve green) hazırlanır. Trafik blue ortamından green ortamına anında yönlendirilir.
Yeni versiyonun küçük bir kullanıcı grubuna önce yayınlanıp, test edildikten sonra tüm kullanıcılara yayınlanmasıdır.
Sistemin dayanıklılığını test etmek için bilinçli olarak hataların (ağ kesintisi, sunucu çökmesi vb.) enjekte edilmesidir.
İş mantığı domain modellerine bölünür, bounded context'ler oluşturulur ve her servis kendi domain sorumluluğunu taşır.
Senior seviye Spring Batch mülakat soruları ve cevapları.
Veri küçük chunk'lara bölünerek okunur, işlenir, yazılır. Bellek dostu ve büyük veriler için uygundur.
Örnek:
@Bean
public Step step() {
return stepBuilderFactory.get("step1")
.<String, String>chunk(100) // her seferinde 100 kayıt
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
Batch job'ların metadata'sını (başlama, bitiş, status, exitCode) saklar. Restart mekanizması buradan yönetilir.
Aynı job farklı parametrelerle yeniden çalıştırılabilir. Parametre verilmezse "job instance already exists" hatası alınır.
Örnek:
JobParameters params = new JobParametersBuilder()
.addString("date", LocalDate.now().toString())
.toJobParameters();
jobLauncher.run(job, params);
Step başarısız olursa aynı parametreyle tekrar başlatılabilir. JobRepository geçmiş durumları track eder.
Büyük datayı bölerek çoklu thread ile işler. Ölçeklenebilirlik sağlar.
Hatalı item atlanabilir ve job çalışmaya devam eder.
Örnek:
.step("step")
.<String, String>chunk(10)
.faultTolerant()
.skip(Exception.class)
.skipLimit(5)
.reader(reader())
.processor(processor())
.writer(writer())
.build();
Geçici hatalarda item tekrar denenebilir.
Örnek:
.faultTolerant() .retry(Exception.class) .retryLimit(3)
Job başlangıcı ve bitişi için listener eklenir.
Örnek:
public class JobCompletionNotificationListener extends JobExecutionListenerSupport {
@Override
public void afterJob(JobExecution jobExecution) {
if(jobExecution.getStatus() == BatchStatus.COMPLETED) {
System.out.println("Job tamamlandı");
}
}
}
Step'ler parallel olarak çalıştırılır.
Örnek:
@Bean
public Job parallelJob() {
return jobBuilderFactory.get("parallelJob")
.start(step1())
.split(new SimpleAsyncTaskExecutor()).add(step2(), step3())
.end()
.build();
}
Aynı job parametreleri ile tekrar çalıştırılabilmesi için unique parametre gerekir.
Örnek:
.incrementer(new RunIdIncrementer())
Büyük veri setlerini paralel işlemek için Partitioning kullanılır.
Örnek:
@Bean
public Step partitionedStep(StepBuilderFactory stepBuilderFactory, Step slaveStep, TaskExecutor taskExecutor) {
return stepBuilderFactory.get("partitionedStep")
.partitioner("slaveStep", new ColumnRangePartitioner())
.step(slaveStep)
.taskExecutor(taskExecutor)
.build();
}
Chunk'lar farklı worker node'lara dağıtılır. Büyük veri paralel işlenir.
Spring Batch job'ları durduğu yerden devam edebilir. Bunun için JobRepository durum bilgisini tutar.
Komut:
java -jar batch-job.jar --spring.batch.job.names=job1
Hangi exception'ların atlanacağını belirler.
Örnek:
@Bean
public SkipPolicy skipPolicy() {
return (t, count) -> t instanceof FlatFileParseException;
}
Bir batch job'un farklı step akışlarını kontrol eder.
Örnek:
@Bean
public Job flowJob(JobBuilderFactory jobs, Step step1, Step step2) {
return jobs.get("flowJob")
.start(step1)
.next(step2)
.end()
.build();
}
Job'ları başlatmak için kullanılan arayüz.
Okunan veriyi işleyip yazıma hazır hale getirir.
ItemReader veriyi okur, ItemWriter veriyi hedefe yazar.
Veriyi doğrulamak için kullanılan processor.
Birden fazla processor'ı birleştirmek için kullanılır.
Job akışını koşullara göre yönlendirmek için kullanılır.
Dosyadan veri okumak için kullanılır.
Veritabanından cursor ile veri okumak için kullanılır.
Birden fazla kaynaktan (dosya) veri okumak için kullanılır.
Senior seviye Spring Caching mülakat soruları ve cevapları.
@Cacheable → Sonuç cache'e kaydedilir.@CacheEvict → Cache temizlenir.Örnek:
@Cacheable("users")
public User getUser(Long id) { ... }
@CacheEvict(value = "users", allEntries = true)
public void clearCache() { }
@CachePut metot çalıştıktan sonra sonucu cache'e günceller.
Örnek:
@CachePut(value="users", key="#user.id")
public User updateUser(User user) {
return repository.save(user);
}
Redis cache provider olarak eklenir.
application.yml:
spring:
cache:
type: redis
redis:
host: localhost
port: 6379
Redis veya caffeine cache'de entry süreli saklanır.
Örnek (Caffeine):
@Bean
public CaffeineCacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("users");
cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES));
return cacheManager;
}
Birden fazla cache anotasyonu gruplamak için kullanılır.
Örnek:
@Caching(
put = { @CachePut(value="users", key="#user.id") },
evict = { @CacheEvict(value="allUsers", allEntries=true) }
)
public User updateUser(User user) { ... }
Koşul sağlandığında caching yapılır.
Örnek:
@Cacheable(value = "users", key = "#id", condition = "#id > 10")
public User getUser(Long id) { ... }
Aynı anda cache miss olduğunda çok sayıda isteğin DB'ye yönlenmesi. Çözüm:
@Cacheable(sync = true) veya locking mekanizması.
Default key generation yerine custom key generator yazılabilir.
Örnek:
@Bean
public KeyGenerator customKeyGenerator() {
return (target, method, params) -> method.getName() + "_" + Arrays.toString(params);
}
Local memory + Distributed cache kombinasyonu. Sık erişilen data local cache'de, nadiren erişilen distributed cache'de tutulur.
Caffeine Örneği:
@EnableCaching
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
return new CaffeineCacheManager("users");
}
}
allEntries = true → tüm cache silinir.beforeInvocation = true → metot çalışmadan önce cache temizlenir.Örnek:
@CacheEvict(value = "users", allEntries = true)
public void clearUsersCache() { }
Koşul sağlandığında cache temizlenir.
Örnek:
@CacheEvict(value = "users", key = "#id", condition = "#id > 10")
public void removeUser(Long id) { }
Caffeine veya EhCache ile hit/miss metric izlenebilir.
Çoklu instance çalışan mikroservislerde, local cache senkron kalmaz. Redis gibi merkezi cache ile consistency sağlanır.
Cache'leri yöneten merkezi bileşendir. Farklı cache sağlayıcıları (Redis, Caffeine, EhCache) için farklı implementasyonları vardır.
Cache miss durumunda sadece bir thread'in veritabanına gitmesini sağlar. Diğer thread'ler bu işlem bitene kadar bekler.
Method sonucuna göre caching yapılıp yapılmayacağını belirler. Koşul sağlanırsa caching yapılmaz.
Örnek:
@Cacheable(value = "users", unless = "#result.age < 18")
public User getUser(Long id) { ... }
Runtime'da hangi cache'in kullanılacağını belirleyen bileşendir.
Cache ayarlarını merkezi olarak yapılandırmak için kullanılır.
Spring caching mekanizmasını aktive eder.
Zamanlanmış görevlerle cache temizlenebilir.
Örnek:
@Scheduled(fixedRate = 60000)
@CacheEvict(value = "users", allEntries = true)
public void clearCachePeriodically() { }
Hazelcast bağımlılığı eklenir ve cache manager yapılandırılır.
EhCache bağımlılığı eklenir ve yapılandırma dosyası oluşturulur.
Veri güncellendiğinde veya silindiğinde cache'in temizlenmesi gerekir. @CacheEvict anotasyonu ile bu sağlanır.
Senior seviye Spring AOP & Events mülakat soruları ve cevapları.
Aspect tanımlanır, @Around ile method öncesi/sonrası log tutulur.
Örnek:
@Aspect
@Component
public class LoggingAspect {
@Around("execution(* com.app.service.*.*(..))")
public Object log(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Before: " + pjp.getSignature());
Object result = pjp.proceed();
System.out.println("After: " + pjp.getSignature());
return result;
}
}
Event yayınlayan (ApplicationEventPublisher) ve dinleyen (@EventListener) bileşenler vardır.
Örnek:
// Event
public class UserCreatedEvent extends ApplicationEvent {
public UserCreatedEvent(User user) { super(user); }
}
// Publisher
publisher.publishEvent(new UserCreatedEvent(user));
// Listener
@EventListener
public void handleUserCreated(UserCreatedEvent event) {
System.out.println("Yeni kullanıcı: " + event.getSource());
}
Hangi methodların intercept edileceğini tanımlar.
Örnek:
@Pointcut("execution(* com.app.service.*.*(..))")
public void serviceMethods(){}
AOP proxy mekanizması ile @Transactional anotasyonu çalışır.
Domain olayları event olarak yayınlanır ve diğer servisler bu olaylara tepki verir.
Örnek:
public class OrderCreatedEvent extends ApplicationEvent {
private final String orderId;
public OrderCreatedEvent(Object source, String orderId) {
super(source);
this.orderId = orderId;
}
}
// Publisher
applicationEventPublisher.publishEvent(new OrderCreatedEvent(this, "1234"));
@Async ile event listener asenkron hale getirilir.
Örnek:
@Async
@EventListener
public void handleEvent(OrderCreatedEvent event) {
System.out.println("Async event: " + event.getOrderId());
}
Method çağrısından önce kullanıcı rolü kontrol edilebilir.
Event sadece transaction commit edildikten sonra publish edilir.
Örnek:
@TransactionalEventListener
public void handleAfterCommit(OrderCreatedEvent event) {
System.out.println("Commit sonrası event işlendi.");
}
Intercept edilebilecek method çağrı noktasıdır.
Method çalıştırma süresi ölçülür ve loglanır.
Örnek:
@Around("execution(* com.example.service.*.*(..))")
public Object monitor(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object retVal = pjp.proceed();
long time = System.currentTimeMillis() - start;
System.out.println(pjp.getSignature() + " çalıştı: " + time + "ms");
return retVal;
}
AfterThrowing advice ile exception loglanabilir veya yönetilebilir.
Örnek:
@AfterThrowing(pointcut = "execution(* com.app.service.*.*(..))", throwing = "ex")
public void logException(Exception ex) {
System.out.println("Hata yakalandı: " + ex.getMessage());
}
Özel bir event publisher sınıfı oluşturulur.
Örnek:
@Component
public class CustomEventPublisher {
@Autowired
private ApplicationEventPublisher publisher;
public void publish(String message) {
publisher.publishEvent(new CustomEvent(this, message));
}
}
Farklı desenlerle method seçimi yapılabilir.
Örnek:
@Pointcut("execution(* com.app.service.*.*(..))")
public void serviceLayer() { }
@Pointcut("within(com.app.controller..*)")
public void controllerLayer() { }
@EventListener anotasyonuna condition eklenerek event filtreleme yapılabilir.
Örnek:
@EventListener(condition = "#event.status == 'COMPLETED'")
public void handleCompleted(OrderEvent event) {
// Sadece tamamlanmış siparişler için çalışır
}
Around advice ile method parametreleri değiştirilebilir.
Örnek:
@Around("execution(* com.app.service.*.*(..)) && args(param)")
public Object changeParameter(ProceedingJoinPoint pjp, Object param) throws Throwable {
// Parametreyi değiştir
Object newParam = transform(param);
// Yeni parametre ile methodu çağır
return pjp.proceed(new Object[]{newParam});
}
Bir event işlendikten sonra başka bir event tetiklenebilir.
Örnek:
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
// Sipariş oluşturulduktan sonra ödeme event'i tetikle
publisher.publishEvent(new PaymentRequestedEvent(this, event.getOrderId()));
}
AspectJ, AOP için daha güçlü bir implementasyondur. Compile time veya load time weaving yapabilir.
@Order anotasyonu ile listener'ların çalışma sırası belirlenebilir.
Örnek:
@EventListener
@Order(1)
public void handleFirst(OrderEvent event) {
// Önce çalışacak
}
@EventListener
@Order(2)
public void handleSecond(OrderEvent event) {
// Sonra çalışacak
}
Özel bir anotasyon oluşturulur ve bu anotasyon için pointcut tanımlanır.
Örnek:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime { }
@Aspect
@Component
public class LogExecutionTimeAspect {
@Around("@annotation(LogExecutionTime)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
// ...
}
}
Generic event'ler için @EventListener kullanılabilir.
Örnek:
@EventListener
public void handleGenericEvent(ApplicationEvent event) {
// Tüm event'leri yakalar
}
Spring AOP, dynamic proxy veya CGLIB kullanarak aspect'leri hedef method'lara bağlar.
@EventListener anotasyonuna condition eklenerek event filtreleme yapılabilir.
Aspect'leri target object'lere bağlama işlemidir. Compile time, load time veya runtime weaving yapılabilir.
Senior seviye Spring Integration mülakat soruları ve cevapları.
Mesajların publisher ile subscriber arasında aktığı kanaldır. QueueChannel, DirectChannel gibi tipleri vardır.
Örnek:
@Bean
public MessageChannel inputChannel() {
return new DirectChannel();
}
Mesaj payload'unu dönüştürmek için kullanılır.
Örnek:
@Transformer(inputChannel="input", outputChannel="output")
public String transform(String message) {
return message.toUpperCase();
}
DSL ile mesaj akışları daha okunabilir şekilde tanımlanır.
Örnek:
@Bean
public IntegrationFlow flow() {
return IntegrationFlows.from("inputChannel")
.filter((String s) -> s.startsWith("A"))
.transform(String::toUpperCase)
.channel("outputChannel")
.get();
}
Mesajın içeriğine göre farklı kanallara yönlendirilmesini sağlar.
Java interface üzerinden messaging dünyasına geçiş sağlar.
Çoklu mesajları birleştirip tek mesaj haline getirir.
Örnek:
@Bean
public IntegrationFlow aggregatorFlow() {
return IntegrationFlows.from("inputChannel")
.aggregate()
.channel("outputChannel")
.get();
}
Bir mesajı birden fazla parçaya böler.
Örnek:
@Bean
public IntegrationFlow splitterFlow() {
return IntegrationFlows.from("inputChannel")
.split(String.class, payload -> payload.split(","))
.channel("outputChannel")
.get();
}
Mesajları belirli kriterlere göre filtreler.
Örnek:
@Bean
public IntegrationFlow filterFlow() {
return IntegrationFlows.from("inputChannel")
.filter((String p) -> p.contains("OK"))
.channel("outputChannel")
.get();
}
Mesajı alıp bir service methodunu çağırır.
Mesajları izlemek için kullanılır, mesajın kopyasını farklı bir kanala gönderir.
Örnek:
@Bean
public IntegrationFlow wiretapFlow() {
return IntegrationFlows.from("inputChannel")
.wireTap("auditChannel")
.channel("outputChannel")
.get();
}
İki farklı channel arasında köprü kurar.
External sistemlerle (dosya, veritabanı, JMS vb.) iletişim kurmak için kullanılır.
MessageBuilder ile mesaj oluşturulur.
Örnek:
Message<String> message = MessageBuilder.withPayload("Hello")
.setHeader("header1", "value1")
.build();
Belirli aralıklarla kaynakları kontrol eder.
Mesajlar transaction kapsamında gönderilir veya rollback edilir.
Hata durumunda mesajları özel bir kanala yönlendirmek için error channel kullanılır.
Büyük veriler geçici olarak depolanır, sadece referansı mesaj olarak gönderilir.
Mesaja ek bilgiler eklemek için kullanılır.
Mesaj birden fazla recipient'e gönderilir ve yanıtlar toplanır.
Java interface üzerinden messaging sistemine erişim sağlar.
Örnek:
@MessagingGateway
public interface OrderGateway {
void processOrder(Order order);
}
Mesajları kalıcı olarak saklamak için kullanılır.
Runtime'da sistem bileşenlerini yönetmek için kullanılır.
Mesajın geçtiği kanalların kaydını tutar.
Senior seviye Spring DevOps mülakat soruları ve cevapları.
Health check, metrics, env bilgisi gibi production izleme endpoint'lerini sağlar.
Örnek:
curl http://localhost:8080/actuator/health
Actuator metrics Prometheus formatında expose edilir.
application.yml:
management:
endpoints:
web:
exposure:
include: prometheus
ConfigMap ve Secret kullanılır.
Örnek:
env:
- name: SPRING_DATASOURCE_URL
valueFrom:
configMapKeyRef:
name: app-config
key: db-url
Yeni versiyon (green) yanına deploy edilir. Trafik yönlendirilince eski versiyon (blue) silinir.
Container'ın sağlık durumunu kontrol eder.
Örnek:
HEALTHCHECK --interval=30s --timeout=5s CMD curl -f http://localhost:8080/actuator/health || exit 1
Uygulama sıfır downtime ile güncellenir.
Komut:
kubectl set image deployment/my-app my-app=image:v2 kubectl rollout status deployment/my-app
Özel endpoint'ler oluşturulabilir.
Örnek:
@Component
@Endpoint(id="custom")
public class CustomEndpoint {
@ReadOperation
public String custom() { return "custom endpoint"; }
}
Özel health indicator'lar oluşturulabilir.
Örnek:
@Component
public class DatabaseHealthIndicator implements HealthIndicator {
@Override
public Health health() {
return Health.up().withDetail("db", "up").build();
}
}
Farklı ortamlar için farklı konfigürasyon dosyaları kullanılır.
Örnek:
spring:
profiles: dev
datasource:
url: jdbc:h2:mem:testdb
Jenkins, GitHub Actions, GitLab CI gibi araçlarla otomatik build, test ve deploy süreçleri oluşturulur.
Sleuth ve Zipkin kullanılarak request'lerin takibi yapılır.
Hystrix Dashboard veya Resilience4j metrics ile circuit breaker durumu izlenir.
VisualVM, JProfiler gibi araçlarla veya heap dump analiz edilerek tespit edilir.
JVM parametreleri ile heap boyutu, garbage collector ayarları yapılır.
Örnek:
java -Xms512m -Xmx1024m -XX:+UseG1GC -jar app.jar
jstack, VisualVM veya Actuator endpoint'i ile thread dump alınabilir.
Actuator ile:
curl http://localhost:8080/actuator/threaddump
jmap, VisualVM veya Actuator endpoint'i ile heap dump alınabilir.
Actuator ile:
curl http://localhost:8080/actuator/heapdump
Kubernetes'te uygulamanın durumunu kontrol etmek için kullanılır.
Örnek:
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
Uygulama kapatılırken mevcut request'lerin tamamlanması sağlanır.
Örnek:
server: shutdown: graceful
Config Server, environment variables, Kubernetes ConfigMap/Secret gibi yöntemlerle konfigürasyon dışarıdan sağlanır.
logback-spring.xml dosyası ile loglama yapılandırılır.
Özel metrikler oluşturmak için kullanılır.
Örnek:
@Autowired
private MeterRegistry meterRegistry;
public void handleRequest() {
Timer.Sample sample = Timer.start(meterRegistry);
try {
// İşlem
} finally {
sample.stop(meterRegistry.timer("request.timer"));
}
}