---
title: 'İşlem Yönetimi'
source: 'https://academia.sh/tr/kurslar/kurumsal-uygulama-cercevesi/islem-yonetimi'
course: 'Kurumsal Uygulama Çerçevesi'
language: tr
updated: '2026-08-23T14:25:05+00:00'
license: 'CC BY-SA 4.0'
---

# İşlem Yönetimi

İki çağrı yolu yan yana koşturuluyor ve bildirimsel işlem sınırının kaç kez açıldığı sayılıyor. Bir bileşenin kendi kendini çağırması vekili atlıyor: iç çağrı için sınır hiç açılmıyor, hiçbir hata çıkmıyor, ve bu sessizlik kaynakta hiçbir yerde işaretli değil.

Önceki ders bir nesnenin alanlarının ne zaman yüklendiğini ölçtü, ama bu yüklemenin ve
üzerindeki değişikliklerin nerede başlayıp nerede bittiği hiç sorulmadı. Bu ders bunu ele
alıyor: bildirimsel bir işlem sınırının kaynakta bir açıklama olduğunu, ve bir bileşenin
kendi kendini çağırmasının bu sınırı nasıl atladığını ölçüyor. İşlemin kendisi — bir dizi
değişikliğin ya tamamen ya hiç uygulanmaması, ve yalıtım düzeyleri — **M17/K04 Veritabanı
Yönetimi** kursunda kavram olarak kuruldu ve burada tekrarlanmıyor; bu dersin sorusu ondan
ayrı: sınırın **nerede açılıp kapandığı**, ve bu sınırı neyin çizdiği.

Gerçek bir veritabanı bağlantısı burada da yok. Bir **işlem sınırı**, `sinirAcilan` adlı bir
sayacın artması olarak modelleniyor — gerçek bir işlemde bu, bir bağlantının işlem kipine
alınması ve sonunda onaylanması ya da geri alınmasıdır; burada yalnız "sınır kaç kez açıldı"
sorusu ölçülüyor, açılan sınırın içinde ne olduğu değil. Bildirimsel sınır, kaynakta hiçbir
`baslatIslemi()` çağrısı olmadan, yalnız bir yöntemin üzerindeki `@Islem` açıklamasından
doğuyor.

"Bildirimsel" sözcüğü tam olarak bunu anlatıyor: sınırı çizen taraf, yöntemi çağıran kod
değil, yöntemin üzerinde duran açıklama. Önceki bir ders bu bildirim biçimini doğrulama
kurallarında görmüştü — bir alanın kısıtlaması da açıklamada duruyordu, onu okuyan taraf
`Kap`'tı. İşlem sınırında fark şu: doğrulamanın uygulanıp uygulanmaması yalnız hangi yöntemin
çağrıldığına bağlıydı, işlem sınırının açılıp açılmaması ise çağrının **nereden geldiğine**
de bağlı. Bu fark, dersin geri kalanının asıl konusu.

## İki Çağrı Yolu, İki Ayrı Sınır Sayısı

- **WV25.** `@Islem`, hem `yatir` hem `yatirVeBildir` yönteminin üzerinde duruyor. İkisi de
  aynı gerçekleştirim sınıfının üyesi.
- **WV26.** Vekil, çağrılan yöntemi hedef nesnenin kendi sınıfında yeniden arayıp
  `@Islem` açıklamasını orada kontrol ediyor; bu, `m.invoke` çağrısından **önce** yapılıyor,
  böylece sınır açma kararı gerçek çağrıdan önce veriliyor.

`HesapGerceklestirimi.yatirVeBildir` kendi içinde `yatir(miktar)`'ı çağırıyor — bu, aynı
nesnenin bir yöntemi kendi başka bir yöntemini çağırması, yani bir **iç çağrı**. `Kap.sarmala`
bu iki yöntemi de bir vekil arkasına koyuyor, ve vekil yalnız **dışarıdan** gelen çağrıları
görüyor.

Ölçüm iki ayrı kurulumla yapılıyor, ve ikisi de aynı gerçekleştirim sınıfını kullanıyor.
Kurulumlar arasındaki tek fark, dışarıdaki çağıranın hangi yöntemleri, kaç kez çağırdığı;
`HesapGerceklestirimi`'nin kendi kaynak kodu iki kurulumda da birebir aynı kalıyor. Bu, önceki
derslerdeki "iki kurulum" ölçümlerinden bir bakımdan farklı: orada değişen şey genellikle
tarama sırası ya da gerçekleştirim seçimiydi, burada değişen şey yalnız **dışarıdan gelen
çağrı deseni**.

```java
// Kap.java — bildirimsel islem siniri aciklamadan doguyor, kendi kendini cagirma vekili atliyor
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;

public class Kap {

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

    static int sinirAcilan = 0;
    static List<String> gunluk = new ArrayList<>();

    @SuppressWarnings("unchecked")
    static <T> T sarmala(T hedef, Class<T> arayuz) {
        return (T) Proxy.newProxyInstance(
                Kap.class.getClassLoader(),
                new Class<?>[]{arayuz},
                (v, m, args) -> {
                    Method gercek = hedef.getClass().getMethod(m.getName(), m.getParameterTypes());
                    if (gercek.isAnnotationPresent(Islem.class)) {
                        sinirAcilan++;
                        gunluk.add("sinir-acildi: " + m.getName());
                    }
                    try {
                        return m.invoke(hedef, args);
                    } catch (InvocationTargetException e) {
                        throw e.getCause();
                    }
                });
    }

    public static void main(String[] args) throws Exception {
        HesapGerceklestirimi gercek = new HesapGerceklestirimi();
        Hesap vekil = sarmala(gercek, Hesap.class);

        System.out.println("-- yol A: yalniz yatirVeBildir digaridan cagriliyor --");
        System.out.println(vekil.yatirVeBildir(100));
        System.out.println("sinir acilma sayisi: " + sinirAcilan);
        System.out.println("gunluk: " + gunluk);

        sinirAcilan = 0;
        gunluk.clear();
        gercek = new HesapGerceklestirimi();
        vekil = sarmala(gercek, Hesap.class);

        System.out.println("-- yol B: yatir ve yatirVeBildir ayri ayri digaridan cagriliyor --");
        System.out.println(vekil.yatir(50));
        System.out.println(vekil.yatirVeBildir(100));
        System.out.println("sinir acilma sayisi: " + sinirAcilan);
        System.out.println("gunluk: " + gunluk);

        System.out.println("-- ic cagrinin kendisi vekili hic gormedi --");
        System.out.println("HesapGerceklestirimi.yatirVeBildir icindeki 'yatir(miktar)' cagrisi "
                + "'this' uzerinden yapiliyor, vekil uzerinden degil");
        System.out.println("dogrulama: yol B'de disaridan iki cagri oldu, ic cagriyla birlikte "
                + "toplamda uc kez yatir/yatirVeBildir calisti, ama sinir yalniz iki kez acildi");
        System.out.println("kusur turu: sessiz (istisna yok, ic cagri icin sinir hic acilmadan calisti)");

        System.out.println("-- elle kurulan nesne: kap hic devrede degil --");
        HesapGerceklestirimi elleKurulan = new HesapGerceklestirimi();
        sinirAcilan = 0;
        System.out.println(elleKurulan.yatirVeBildir(100));
        System.out.println("sinir acilma sayisi (vekil hic kurulmadi): " + sinirAcilan);
    }
}

interface Hesap {
    String yatir(int miktar);
    String yatirVeBildir(int miktar);
}

class HesapGerceklestirimi implements Hesap {
    int bakiye = 0;

    @Kap.Islem
    public String yatir(int miktar) {
        bakiye += miktar;
        return "bakiye=" + bakiye;
    }

    @Kap.Islem
    public String yatirVeBildir(int miktar) {
        String sonuc = yatir(miktar);
        return sonuc + "; bildirildi";
    }
}
```

```
-- yol A: yalniz yatirVeBildir digaridan cagriliyor --
bakiye=100; bildirildi
sinir acilma sayisi: 1
gunluk: [sinir-acildi: yatirVeBildir]
-- yol B: yatir ve yatirVeBildir ayri ayri digaridan cagriliyor --
bakiye=50
bakiye=150; bildirildi
sinir acilma sayisi: 2
gunluk: [sinir-acildi: yatir, sinir-acildi: yatirVeBildir]
-- ic cagrinin kendisi vekili hic gormedi --
HesapGerceklestirimi.yatirVeBildir icindeki 'yatir(miktar)' cagrisi 'this' uzerinden yapiliyor, vekil uzerinden degil
dogrulama: yol B'de disaridan iki cagri oldu, ic cagriyla birlikte toplamda uc kez yatir/yatirVeBildir calisti, ama sinir yalniz iki kez acildi
kusur turu: sessiz (istisna yok, ic cagri icin sinir hic acilmadan calisti)
-- elle kurulan nesne: kap hic devrede degil --
bakiye=100; bildirildi
sinir acilma sayisi (vekil hic kurulmadi): 0
```

Yol A'da tek bir dış çağrı var — `vekil.yatirVeBildir(100)` — ve sınır bir kez açılıyor. Yol
B'de iki dış çağrı var — `vekil.yatir(50)` ve `vekil.yatirVeBildir(100)` — ve sınır iki kez
açılıyor. İkisi arasındaki fark yalnız **dışarıdan kaç çağrı yapıldığı**; `yatirVeBildir`'in
kendi içinde `yatir`'ı çağırması hiçbir kurulumda sınır sayısına eklenmiyor. Bu, kursun
**yayılım** dediği şeyin en yalın hâli: bir iç çağrının kendi sınırını mı açacağı, yoksa
dışarıdaki sınırın içinde mi kalacağı sorusu — burada yanıt üçüncü bir olasılık, iç çağrının
**hiçbir sınıra hiç girmemesi**, çünkü vekil onu hiç görmüyor.

## İç Çağrı Vekili Hiç Görmüyor

- **WV27.** `sarmala` yalnız `Hesap` arayüzünü uygulayan bir vekil nesnesi döndürüyor;
  `HesapGerceklestirimi`'nin kendisi hiç değişmiyor, `this` hâlâ gerçek nesneyi gösteriyor.
- **WV28.** Vekilin araya girebilmesi için bir çağrının onun ürettiği nesne üzerinden
  geçmesi gerekiyor. `yatirVeBildir` içindeki `yatir(miktar)` çağrısı bu nesneyi hiç
  kullanmıyor.

Bunun nedeni, vekilin nasıl çalıştığında yatıyor. `Proxy.newProxyInstance` yeni bir nesne
üretiyor — `vekil` — ve bu nesne dışarıdan gelen her çağrıyı yakalayıp `sinirAcilan`'ı
artırdıktan sonra gerçek nesneye (`hedef`) yönlendiriyor. Ama `HesapGerceklestirimi` sınıfının
kendi kaynak kodu içinde `yatir(miktar)` yazıldığında, bu çağrı `hedef.yatir(miktar)` değil,
**gerçek nesnenin kendi `this`'i üzerinden** yapılan sıradan bir Java yöntem çağrısı. Nesnenin
kendisi hiçbir zaman "ben bir vekilin arkasındayım" bilgisine sahip değil — vekil, nesnenin
etrafına konan ayrı bir katman, nesnenin bir parçası değil. Bu yüzden `yatir`'in üzerindeki
`@Islem` açıklaması, bu iç çağrı için hiçbir zaman okunmuyor: onu okuyacak taraf yalnız
vekilin çağrı işleyicisi, ve çağrı işleyicisi yalnız vekil üzerinden geçen çağrıları görüyor.

Bu, dersin sınırlayıcı ölçümü: **bir bileşenin kendi kendini çağırması vekili atlar ve
açıklama hiç uygulanmaz — çağrı içeriden geldiği için sarmalama devreye girmez, hata çıkmaz,
sınır açılmaz.** Yol B'nin günlüğü bunu doğruluyor: `yatir` ve `yatirVeBildir` toplam üç kez
çalıştı (dışarıdan iki, içeriden bir), ama günlükte yalnız iki `sinir-acildi` girdisi var. Ne
bir istisna fırlıyor ne bir uyarı basılıyor — program tamamen normal görünen bir yanıt
üretiyor, `bakiye=150; bildirildi`. Kaynak metni okuyan biri `yatir`'in üzerinde `@Islem`
gördüğü için onun her çağrıldığında bir sınır açacağını varsayabilir; bu varsayım
`yatirVeBildir` üzerinden gelen çağrılar için yanlış, ve yanlışlığı gösteren tek şey sayaç,
hiçbir hata mesajı değil.

Bu davranışın kökü, vekilin kurulma biçiminde. `Kap.sarmala` yeni bir nesne **üretiyor**,
var olan nesneyi **değiştirmiyor** — `HesapGerceklestirimi`'nin kendi bayt kodunda hiçbir
satır eklenmedi, hiçbir yöntem araya giren bir çağrıyla değiştirilmedi. Vekil, `hedef`'i saran
ayrı bir sınıfın çalışma zamanında üretilen bir örneği, ve bu örnek yalnız `Hesap` arayüzünü
uyguladığı için, arayüz üzerinden gelen çağrılar dışında hiçbir yola dahil değil. Bir
gerçekleştirim sınıfının içine yazılmış bir çağrı, o sınıfın kendi tanıdığı tek nesneyi
görüyor: kendisi. Vekilin varlığından habersiz olmak, gerçekleştirim sınıfının bir eksikliği
değil — vekil zaten sınıfın kendisine hiçbir iz bırakmadan, tamamen dışarıdan ekleniyor.

## Elle Kurulan Nesnede Sınır Hiç Açılmıyor

Son ölçüm `sarmala` hiç çağrılmadan kurulan bir `HesapGerceklestirimi` nesnesiyle yapılıyor.
`elleKurulan.yatirVeBildir(100)` çağrısı normal şekilde tamamlanıyor, `bakiye=100;
bildirildi` döndürüyor — ama `sinirAcilan` sıfırda kalıyor. Bu, önceki derslerde defalarca
görülen kuralın işlem yönetimindeki karşılığı: `@Islem` açıklaması `HesapGerceklestirimi`
sınıfının üzerinde durmaya devam ediyor, ama onu okuyacak bir vekil hiç kurulmadıysa hiçbir
sınır hiçbir zaman açılmıyor. Yol B'deki iç çağrı ile bu elle kurulan nesne arasındaki fark
ince ama önemli: iç çağrıda vekil **var**, yalnız o çağrı için devreye girmiyor; elle kurulan
nesnede vekil **hiç yok**. İkisi de aynı sonucu — sınırın açılmaması — üretiyor, ama
biri nesne kabının kendi kuralından (yalnız dışarıdan gelen çağrılar sarmalanır), öteki kabın hiç
devrede olmamasından geliyor.

Bu üç kurulumun birlikte gösterdiği şey şu: bildirimsel bir sınırın var olduğunu bilmek,
onun **her zaman** çalışacağını bilmek anlamına gelmiyor. Sınırın açılması üç koşula birden
bağlı — açıklama sınıfın üzerinde olmalı, çağrı vekil üzerinden geçmeli, ve çağrı dışarıdan
gelmeli. Üçü de sağlanmadığı sürece, kaynakta `@Islem` yazması hiçbir şey garanti etmiyor.

Bu üç koşulun hiçbiri kaynak metninde tek bir yerde toplu olarak yazılı değil. `@Islem`
açıklaması `HesapGerceklestirimi`'nin içinde, vekil kurulumu `main`'in içinde, ve çağrının
dışarıdan mı içeriden mi geldiği yalnız çağrının **hangi değişken üzerinden** yapıldığına
bakılarak anlaşılabiliyor — `vekil.yatir(...)` mı, `this.yatir(...)`'e denk gelen çıplak
`yatir(...)` mu. Bu üç bilgiyi aynı anda tutmak, bir kod incelemesinin gözden
kaçırabileceği bir şey: `yatirVeBildir` yönteminin gövdesine bakan biri, `yatir` çağrısının
hangi nesne üzerinden yapıldığını fark etmeden geçebilir, çünkü Java söz dizimi `yatir(...)`
ile `this.yatir(...)`'i ayırt etmiyor — ikisi aynı çağrı, aynı görünüm.

## Özet

- Yalnız `yatirVeBildir`'in dışarıdan çağrıldığı yolda sınır bir kez açıldı; `yatir` ile
  `yatirVeBildir`'in ayrı ayrı dışarıdan çağrıldığı yolda sınır iki kez açıldı.
- `yatirVeBildir` içindeki `yatir(miktar)` iç çağrısı hiçbir kurulumda sınır sayısına
  eklenmedi; vekil yalnız dışarıdan gelen çağrıları görüyor.
- İç çağrı `this` üzerinden yapıldığı için vekili hiç görmedi; `@Islem` açıklaması sınıfın
  üzerinde durmaya devam etse de bu çağrı için hiç okunmadı.
- Kusur sessizdi: iç çağrı ne bir istisna fırlattı ne bir uyarı bastı, yalnız beklenen
  sınırı açmadan tamamlandı.
- Vekil hiç kurulmadan çağrılan aynı sınıfta sınır bir kez bile açılmadı; sınırın
  çalışması açıklamanın varlığına değil, üç koşulun birlikte sağlanmasına bağlı.

## Sonraki Adım

B payı burada kapanıyor. Bu ders sınırın nerede açıldığını bir açıklamanın söylediğini, ve
içeriden gelen bir çağrının o sınırı hiç görmediğini gösterdi. Sıradaki konu aynı soruyu
başka bir yerde soruyor: güvenlik, test ve dağıtık kurulumda da bir sınır — bu kez bir yetki
sınırı — yine bir açıklamayla çiziliyor, ve içeriden gelen bir çağrının onu görüp görmediği
yeniden ölçülüyor.
