Command Palette

Search for a command to run...

PHASE 2Beginner ~7 min· topic 9 of 22Structural

Structural 4 — Proxy

In one line

A stand-in that controls access to the real object: lazy init, access control, caching, remote calls.

0/22 · 0%

Think of it like this

A security guard at an office. You can't walk straight to the CEO; the guard checks your ID first, and then lets you through. The guard stands in for the real thing and controls access.

Key ideas

  1. 01

    Virtual proxy: build the expensive object only when used.

  2. 02

    Protection proxy: check permissions before delegating.

  3. 03

    Lazy-loading ORM proxies are the classic real-world example.

  4. 04

    Proxy vs Decorator: proxy controls access/lifecycle, decorator adds behavior.

Java / Spring map

  • →

    java.lang.reflect.Proxy; Spring AOP proxies; Hibernate lazy proxies.

  • →

    Spring gotcha: @Transactional and @Cacheable work through a proxy, so a self-invocation (this.method()) bypasses them. This is a classic interview question.

Code & diagrams

Proxies.javajava

A protection proxy and a lazy virtual proxy, each behind the same interface as the real object.

public interface DocumentStore { byte[] read(String docId, User u); }

public final class S3DocumentStore implements DocumentStore {
  public byte[] read(String docId, User u) { /* network call */ return new byte[0]; }
}

// Protection proxy: access control before delegation.
public final class AuthorizingDocumentStore implements DocumentStore {
  private final DocumentStore real;
  private final Acl acl;
  public AuthorizingDocumentStore(DocumentStore real, Acl acl) { this.real = real; this.acl = acl; }
  public byte[] read(String docId, User u) {
    if (!acl.canRead(u, docId)) throw new AccessDeniedException(docId);
    return real.read(docId, u);
  }
}

// Virtual proxy: defers the expensive construction until first use.
public final class LazyDocumentStore implements DocumentStore {
  private final Supplier<DocumentStore> factory;
  private volatile DocumentStore real;
  public LazyDocumentStore(Supplier<DocumentStore> f) { this.factory = f; }
  public byte[] read(String docId, User u) {
    DocumentStore r = real;
    if (r == null) {
      synchronized (this) { if ((r = real) == null) real = r = factory.get(); }
    }
    return r.read(docId, u);
  }
}

Explain without notes

01

Lazy-load proxy on a User entity — which methods trigger the load?

02

Why doesn't @Transactional apply when a bean calls its own annotated method?

Practice

01

Write a CachingProxy over a slow WeatherService that caches by city.

Trade-offs

  • ↔

    Proxies add indirection and hide the real object's identity. Lazy proxies can also surprise you with LazyInitializationException outside a session.

Completion checklist

  • I can name three proxy types (virtual, protection, remote) and explain the Spring self-invocation trap.

Back to phase