@StaticVirtualProxy

Generate a lazy-creation wrapper for an interface at compile time.

@StaticVirtualProxy generates a wrapper class backed by the virtual proxy strategy infrastructure. The wrapper holds a creation strategy; the real implementation is built on first use and cached.

Usage

import com.svenruppert.proxybuilder.proxy.generated.annotations.StaticVirtualProxy;

@StaticVirtualProxy
public interface Service {
  String work(String input);
}

After compilation, the generator produces ServiceStaticVirtualProxy. Configure it with a factory and the first call materialises the real instance:

Service proxy = new ServiceStaticVirtualProxy()
    .withStrategy(new SingleInstanceCreationStrategy<>(() -> new ServiceImpl()));

proxy.work("hello");   // first call — constructs ServiceImpl, then delegates
proxy.work("again");   // reuses the already-constructed ServiceImpl

What “virtual” buys you

  • Lazy construction. The expensive implementation is not built at proxy creation time; it is built when something actually calls a method.
  • Thread safety. The default strategy is single-instance and thread-safe. Multiple threads racing on the first call will see one construction and the same cached instance.
  • Pluggable lifecycle. Swap in a custom CreationStrategy for caching with eviction, per-thread instances, or test fixtures that build a fresh instance each round.

When to prefer this over the runtime version

  • You want the compile-time benefits — no reflection, GraalVM-friendly, inspectable generated source.
  • You want the proxy to live in a JPMS module and be referenced by other modules without runtime opens.

When the runtime version is fine

  • You build the proxy in one place, hand it to one consumer, and never need to inspect the generated source.

See also

  • The strategy classes live under com.svenruppert.proxybuilder.proxy.dymamic.virtual.strategy.
  • The runtime counterpart: virtual proxies at runtime.

Edit this page on GitHub ↗