Proxy
Provide a surrogate or placeholder for another object to control access to it.
Sometimes you want to do something extra whenever an object is used. Load it only when first needed. Cache the results. Check permissions. Log the call.
Putting that logic inside the object mixes two concerns. Putting it in every caller repeats it everywhere.
A proxy is a stand-in. It implements the same interface as the real object, so callers cannot tell the difference. It does the extra work, then passes the call along.
What the interviewer is probing.
1. "What kinds of proxy are there?" *Probing:* the breadth. *Stalls:* "One kind." *Moves up:* virtual for lazy loading, protection for access control, remote for a different address space, and smart for added behaviour such as caching.
2. "How does it differ from Decorator?" *Probing:* the distinction. *Stalls:* "They are the same." *Moves up:* structurally similar, but intent differs — Decorator adds behaviour, Proxy controls access to the real subject.
3. "Where does Spring use proxies?" *Probing:* the framework knowledge. *Stalls:* "Nowhere." *Moves up:* @Transactional, @Async, caching and method security — which is exactly why self-invocation bypasses them.
4. "What is the lazy-loading proxy risk?" *Probing:* the practical failure. *Stalls:* "None." *Moves up:* accessing it outside the session, which in JPA raises LazyInitializationException at the view layer.
A credit card is a proxy for your bank account — same 'pay' interface but adds authorization and logging.
Key Concepts
public interface YouTubeLib {
List<Video> listVideos();
Video getVideoInfo(String id);
}
public class CachedYouTubeProxy implements YouTubeLib {
private final YouTubeService service;
private List<Video> listCache;
private final Map<String, Video> videoCache = new HashMap<>();
public List<Video> listVideos() {
if (listCache == null) listCache = service.listVideos();
return listCache;
}
public Video getVideoInfo(String id) {
return videoCache.computeIfAbsent(id, service::getVideoInfo);
}
}