{"id":15044398,"url":"https://github.com/svenruppert/proxybuilder","last_synced_at":"2026-04-04T12:57:36.307Z","repository":{"id":31386126,"uuid":"34949232","full_name":"svenruppert/proxybuilder","owner":"svenruppert","description":null,"archived":false,"fork":false,"pushed_at":"2026-02-16T21:25:34.000Z","size":677,"stargazers_count":24,"open_issues_count":42,"forks_count":9,"subscribers_count":9,"default_branch":"develop","last_synced_at":"2026-04-02T22:27:10.843Z","etag":null,"topics":["dynamicproxy","java","java-library","java8","java9","metrics","proxies"],"latest_commit_sha":null,"homepage":"http://www.proxybuilder.org","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/svenruppert.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2015-05-02T13:43:48.000Z","updated_at":"2025-06-16T08:09:15.000Z","dependencies_parsed_at":"2022-08-17T18:55:23.125Z","dependency_job_id":"b72ac73b-3338-4ec8-a202-3463b3e033e0","html_url":"https://github.com/svenruppert/proxybuilder","commit_stats":{"total_commits":178,"total_committers":6,"mean_commits":"29.666666666666668","dds":0.0955056179775281,"last_synced_commit":"c96c05a68c2b24abe92ade8e708629538670743d"},"previous_names":["rapidpm/proxybuilder","proxybuilder/proxybuilder"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/svenruppert/proxybuilder","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenruppert%2Fproxybuilder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenruppert%2Fproxybuilder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenruppert%2Fproxybuilder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenruppert%2Fproxybuilder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/svenruppert","download_url":"https://codeload.github.com/svenruppert/proxybuilder/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenruppert%2Fproxybuilder/sbom","scorecard":{"id":114772,"data":{"date":"2025-08-04","repo":{"name":"github.com/svenruppert/proxybuilder","commit":"c96c05a68c2b24abe92ade8e708629538670743d"},"scorecard":{"version":"v5.2.1-28-gc1d103a9","commit":"c1d103a9bb9f635ec7260bf9aa0699466fa4be0e"},"score":3.2,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during GetBranch(master): error during branchesHandler.query: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-2qp4-g3q3-f92w","Warn: Project is vulnerable to: GHSA-cqj8-47ch-rvvq"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-16T00:52:12.368Z","repository_id":31386126,"created_at":"2025-08-16T00:52:12.368Z","updated_at":"2025-08-16T00:52:12.368Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31400460,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dynamicproxy","java","java-library","java8","java9","metrics","proxies"],"created_at":"2024-09-24T20:50:32.535Z","updated_at":"2026-04-04T12:57:36.291Z","avatar_url":"https://github.com/svenruppert.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Welcome to ProxyBuilder\n# Welcome to ProxyBuilder\n\nHere we will describe the ProxyBuilder \nfrom [github.com/ProxyBuilder/proxybuilder](https://github.com/ProxyBuilder/proxybuilder)\n\n## What are Proxies ?\nIf you want to have an overview of the Proxy-Pattern itself I can recommend\nthe following sources.\n\n[JavaOne 2015 Tutorial - Proxy DeepDive](https://de.slideshare.net/svenruppert/proxy-deepdive-javaone20151027001)\n\n## What goal we want to reach?\nThis project was born, because I had to work a lot with old huge projects. The only thing I could rely on, is the pure JDK.\nSo I started playing with different Design Patterns and figured out, that Proxies are one of the most powerful pattern group for me.\nDuring the time I was writing the german Book ***\"Dynamic Proxies\"*** with [Dr. Heinz Kabutz](http://www.javaspecialists.eu/) I started to write examples. Step by step the examples are more generic and the ***ProxyBuilder*** - project was born. \n\n## Some Examples\nTo have an idea what you could do with the ***ProxyBuilder*** I will show here some examples. The more detailed \ninformation you can find in the special sections of this website. This project is based on ***Java8***.\n\n### Some Examples with DynamicProxies\nHere are some examples based on the ***DynamicProxy***. But we have created ***generated static*** versions too...\n#### Virtual Proxy\n```java\nfinal DemoLogic original = new DemoLogic();\nfinal DemoInterface demoLogic = VirtualProxyBuilder\n        .createBuilder(DemoInterface.class, original)\n        .build();\n```\n\n#### Security Proxy\n```java\nfinal DemoLogic original = new DemoLogic();\nfinal DemoInterface demoLogic = VirtualProxyBuilder\n        .createBuilder(DemoInterface.class, original)\n        .addSecurityRule(() -\u003e false)\n        .build();\n```\n\n\n```java\nfinal InnerDemoClass original = new InnerDemoClass();\n    final InnerDemoInterface demoLogic = VirtualProxyBuilder\n        .createBuilder(InnerDemoInterface.class, original)\n        .addSecurityRule(() -\u003e true)\n        .addSecurityRule(() -\u003e true)\n        .addSecurityRule(() -\u003e false)\n        .build();\n```\n\n#### Metrics Proxy\n```java\n    final InnerDemoClass original = new InnerDemoClass();\n    final InnerDemoInterface demoLogic = VirtualProxyBuilder\n        .createBuilder(InnerDemoInterface.class, original)\n        .addMetrics()\n        .build();\n\n```\n\n## How to bootstrap your project?\nIf you want to be as near as possible at the actual development version, you could use this. If you need a more stable version\nchange the version numbers to the last stable one.\n\nIf you want to start with the ***DynamicProxyBuilder*** creating for example ***VirtualProxies*** bundled with some other things\nyou need the following dependency in your pom.xml:\n\n```xml\n    \u003cdependency\u003e\n      \u003cgroupId\u003eorg.rapidpm.proxybuilder\u003c/groupId\u003e\n      \u003cartifactId\u003erapidpm-proxybuilder-modules-dynamic\u003c/artifactId\u003e\n      \u003cversion\u003e${rapidpm.version}\u003c/version\u003e\n    \u003c/dependency\u003e\n```\n\nThe ***ProxyBuilder*** includes the ***Kotlin*** runtime libs and ***Metrics*** from Dropwizard. \n\n### VirtualProxy with one PreAction\nThis will be a ***VirtualProxy*** with a ***PreAction***. You can add as many ***PreActions*** as you need. \nEvery ***PreAction*** will be executed before every method invocation in the order the ***PreAction*** was added.\n\n```java\npublic class ProxyDemoV001 {\n\n  public static void main(String[] args) {\n  \n    final Service service = DynamicProxyBuilder\n        .createBuilder(Service.class, new ServiceImpl())\n        .addIPreAction((original, method, args1) \n                        -\u003e System.out.println(\" PreAction = \" + System.nanoTime()))\n        .build();\n  \n    System.out.println(\"proxy created \" + System.nanoTime());\n    System.out.println(\"s = \" + service.doWork(\"Go..\"));\n  }\n\n  public interface Service {\n    String doWork(String str);\n  }\n\n  public static class ServiceImpl implements Service {\n    public ServiceImpl() {\n      System.out.println(\" ServiceImpl =\u003e constructor... \" + System.nanoTime());\n    }\n\n    @Override\n    public String doWork(final String str) {\n      return str + \" orig..\";\n    }\n  }\n\n}\n\n```\n\n### VirtualProxy with Metrics\n\n```java\npublic class ProxyDemoV002 {\n\n  public static void main(String[] args) {\n    RapidPMMetricsRegistry.getInstance().startConsoleReporter();\n    \n    final Service service = DynamicProxyBuilder\n        .createBuilder(Service.class, new ServiceImpl())\n        .addMetrics()\n        .build();\n        \n    System.out.println(\"proxy created \" + System.nanoTime());\n    final long count = IntStream.range(0, 10_000_000)\n        .boxed()\n        .map(i -\u003e service.doWork(\"Go..\" + i))\n        .count();\n    System.out.println(\"s = \" + service.doWork(\"Go..\"));\n    System.out.println(\"count = \" + count);\n  }\n\n\n  public interface Service {\n    String doWork(String str);\n  }\n\n  public static class ServiceImpl implements Service {\n    public ServiceImpl() {\n      System.out.println(\" ServiceImpl =\u003e constructor... \" + System.nanoTime());\n    }\n    @Override\n    public String doWork(final String str) {\n      return str + \" orig..\";\n    }\n  }\n}\n```\n\n\n\nTo bootstrap your project with the latest SNAPSHOT you need to add the SNAPSHOT-repository that is available at maven - central.  \nHere our ***TeamCity*** will push regularly the binaries. \nIf you are using maven you could add the following to your ***settings.xml*** to get the snapshots that are available at maven-central. \n\n```xml\n   \u003cprofile\u003e\n      \u003cid\u003eallow-snapshots\u003c/id\u003e\n      \u003cactivation\u003e\n        \u003cactiveByDefault\u003etrue\u003c/activeByDefault\u003e\n      \u003c/activation\u003e\n      \u003crepositories\u003e\n        \u003crepository\u003e\n          \u003cid\u003esnapshots-repo\u003c/id\u003e\n          \u003curl\u003ehttps://oss.sonatype.org/content/repositories/snapshots\u003c/url\u003e\n          \u003creleases\u003e\n            \u003cenabled\u003efalse\u003c/enabled\u003e\n          \u003c/releases\u003e\n          \u003csnapshots\u003e\n            \u003cenabled\u003etrue\u003c/enabled\u003e\n            \u003cupdatePolicy\u003ealways\u003c/updatePolicy\u003e\n          \u003c/snapshots\u003e\n        \u003c/repository\u003e\n      \u003c/repositories\u003e\n    \u003c/profile\u003e\n``` \n\n# Static Proxies\nCompared to the DynamicProxies we are now generating static proxies. This could be done with \n***AnnotationProcessing*** during the compile process or at runtime.\n\n## Generated\nUsing ***AnnotationProcessing*** to generate the Proxies will give you the possibility to get \nproxies without the overhead of Reflection. On the other side you will generate maybe a lot of code, that must be compiled.\n\n## Runtime Generated\nCompared to the way of using ***AnnotationProcessing*** this one will create and compile at runtime the static proxies. This\nis possible if you have access to the Compiler (tools.jar) during runtime and will mostly lead you to use Unsafe to put your new classes to the SystemClassLoader.\n\n## Static Generated VirtualProxy\nWith the Annotation ***@StaticVirtualProxy*** you can generate Static - VirtualProxies during the clean compile process. This Annotation have a parameter called ***strategy***. The Strategy is used to define the right time to call the ***InstanceFactory***\nSee [DynamicProxies - CreationStrategies](/dynamicproxy/#creationstrategies)\n\n\n## Static Generated MetricsProxy\nWith the static ***MetricsProxy*** we will get generated MetricsProxies that are using Dropwizard-Metrics to measure the \nusage of the methods. The generated static MetricsProxies are generating Methods for all declared Methods in the inheritance including ***hashCode()*** and ***equals()***. You can use the Annotation  ***@StaticMetricsProxy*** in combination with interfaces and classes.\n\nThere is one difference between the generated classes based on interfaces and classes. If you annotate an interface you will only get Metrics for the declared Methods, not for ***hashCode*** and ***equals*** if it is not explicitly declared. But for annotated classes you will get the Metrics for methods from Object, too.\n\n```java\n@StaticMetricsProxy\npublic interface Service {\n  String doWork(String txt);\n\n  String doMoreWorkA(String txt);\n\n  String doMoreWorkB(String txt);\n\n  String doMoreWorkC(String txt);\n\n  String doMoreWorkD(String txt);\n}\n```\n\nYou can use the MetricsProxy easily by creating an instance and setting the Delegator. After this\nevery Methodcall will be counted by DropwizardMetrics. For every Method, you will get a separate Histogram, named with the full Classname and Methodname. In my case you will get a Histogram with the name\n***org.rapidpm.demo.proxybuilder.staticproxy.v002.Service.doMoreWorkC***\n\n\n```java\n    final ServiceStaticMetricsProxy proxy = new ServiceStaticMetricsProxy();\n    proxy.withDelegator(new ServiceImpl());\n\n    final Service service = proxy;\n\n    RapidPMMetricsRegistry.getInstance().startConsoleReporter();\n    try (final IntStream intStream = IntStream.range(0, 10_000_000)) {\n      intStream\n          .onClose(() -\u003e out.println(\"Stream will be closed now...\"))\n\n          .forEach(i -\u003e service.doMoreWorkC(\"aaahhhhhh \" + i));\n    }\n\n    RapidPMMetricsRegistry\n        .getInstance()\n        .getMetrics()\n        .getHistograms()\n        .forEach((s, histogram) -\u003e {\n          out.println(\"s = \" + s);\n          out.println(\"histogram - get999thPercentile= \" + histogram.getSnapshot().get999thPercentile());\n        });\n```\n\n## Static Generated LoggingProxy\nQuite often I could find source code like the following.\n```java\npublic void doWork(String str){\n    logger.debug(\"doWork -\u003e \" + str);\n    //some work....\n}\n```\n\nThe target is a logging of the methodcalls and the values. OK, we don´t want to discuss why or why not. But if you have to do it, you could\nnow use the ***LoggingProxy***. The Logging is implemented with ***slf4j***. Every method call will be logged with \nthe methodname, the name of the params and the param values itself. With this information you could find the corresponding source code very easy.\n\nBased on the following definition of a method...\n```java\n    public \u003cT extends List\u003e T unwrapList(final T type, final String str);\n``` \nyou will get an implementation like the follwoing.\n\n```java\n  public \u003cT extends List\u003e T unwrapList(final T type, final String str) {\n    if (logger.isInfoEnabled()) {\n      logger.info(\"delegator.unwrapList(type, str) values - \" + type + \" - \" + str);\n    }\n    T result = delegator.unwrapList(type, str);\n    return result;\n  }\n```\n\nThis implementation will asume, that the values are using a proper ***toString()*** implementation itself.\n\nIf you want to generate a StaticLoggingProxy, please add the Annotation ***@StaticLoggingProxy*** to the target class or interface.\n\nHere you will get the full example.\n```java\n@StaticLoggingProxy\npublic interface MyLoggingInterface {\n  \u003cT extends List\u003e T unwrapList(T type, String str);\n}\n\n//generated code\n@Generated(\n    value = \"StaticLoggingProxyAnnotationProcessor\",\n    date = \"2016-05-09T14:40:56.22\",\n    comments = \"www.proxybuilder.org\"\n)\n@IsGeneratedProxy\n@IsLoggingProxy\npublic class MyLoggingInterfaceStaticLoggingProxy implements MyLoggingInterface {\n  private static final Logger logger = getLogger(MyLoggingInterface.class);\n\n  private MyLoggingInterface delegator;\n\n  public MyLoggingInterfaceStaticLoggingProxy withDelegator(final MyLoggingInterface delegator) {\n    this.delegator = delegator;\n    return this;\n  }\n\n  public \u003cT extends List\u003e T unwrapList(final T type, final String str) {\n    if(logger.isInfoEnabled()) {\n      logger.info(\"delegator.unwrapList(type, str) values - \" + type + \" - \" + str);\n    }\n    T result = delegator.unwrapList(type, str);\n    return result;\n  }\n}\n\n// demo code usage\npublic class MainV008 {\n  public static void main(String[] args) {\n    final MyLoggingInterface demo\n        = new MyLoggingInterfaceStaticLoggingProxy()\n        .withDelegator(new LoggerExample());\n    final List\u003cInteger\u003e list = demo.unwrapList(asList(1,2,3,4), \"AEAEA\");\n  }\n\n  public static class LoggerExample implements MyLoggingInterface {\n    @Override\n    public \u003cT extends List\u003e T unwrapList(final T type, final String str) {\n      return null;\n    }\n  }\n}\n```\n\nThe logging output will be ```delegator.unwrapList(type, str) values - [1, 2, 3, 4] - AEAEA```\n\n\n## Static Runtime VirtualProxy\npartly implemented until now.. stay tuned\n\n## Static Runtime MetricsProxy\npartly implemented until now.. stay tuned\n\n#DynamicProxy\n\nSince jdk1.3 the DynamicProxy is part of the JDK. \nThe official documentation/API-Doc for JDK8 you can find \n[here](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html)\n\nTo create Proxies based on the DynamicProxy you have to add the following dependency to your project.\n'''xml\n \u003cdependency\u003e\n      \u003cgroupId\u003eorg.rapidpm.proxybuilder\u003c/groupId\u003e\n      \u003cartifactId\u003erapidpm-proxybuilder-modules-dynamic\u003c/artifactId\u003e\n      \u003cversion\u003e${rapidpm.version}\u003c/version\u003e\n    \u003c/dependency\u003e\n'''\n\nIf you are working with this kind of Proxies, you need always an interface. If you don´t have an interface in your code and you could not create one, you have to use the ***StaticVirtualProxies***.\n\n##VirtualProxy\n\n#### pure VirtualProxy\n```java\nfinal DemoLogic original = new DemoLogic();\nfinal DemoInterface demoLogic = VirtualProxyBuilder\n        .createBuilder(DemoInterface.class, original)\n        .build();\n```\nWith this you can generate at runtime a ***VirtualProxy*** based on the ***DynamicProxy***. This you can use beginning from Java 1.3 if you need it. (You have to backport the code by yourself, but we would like to add this as legacy module) The Sourcelevel we are using in this project is Java8.\n\n#### Security Proxy\n```java\nfinal DemoLogic original = new DemoLogic();\nfinal DemoInterface demoLogic = VirtualProxyBuilder\n        .createBuilder(DemoInterface.class, original)\n        .addSecurityRule(() -\u003e false)\n        .build();\n```\nThis is a SecureVirtalProxy. The SecurityRules are invoked before the VirtualProxy is activated. This means, the real Subject will be created after the first time all SecurityRules are OK. \n\n```java\nfinal InnerDemoClass original = new InnerDemoClass();\n    final InnerDemoInterface demoLogic = VirtualProxyBuilder\n        .createBuilder(InnerDemoInterface.class, original)\n        .addSecurityRule(() -\u003e true)\n        .addSecurityRule(() -\u003e true)\n        .addSecurityRule(() -\u003e false)\n        .build();\n```\n\n#### Metrics Proxy\n\nIf you need the possibility to get Metrics out of your application, you could create a MetricsProxy. In this example we are creating a pure ***MetricsProxy*** you could do the following:\n\n```java\n    final InnerDemoInterface demoLogic = VirtualProxyBuilder\n        .createBuilder(InnerDemoInterface.class, new InnerDemoClass())\n        .addMetrics()\n        .build();\n\n```\n You could combine this with a ***VirtualProxy*** to get a ***VirtualMetricsProxy***:\n\n```java\n    final Service service = DynamicProxyBuilder\n        .createBuilder(Service.class, ServiceImpl.class, CreationStrategy.SOME_DUPLICATES)\n        .addMetrics()\n        .build();\n\n```\n\n## PreAction -- PostAction\nSometimes you want to have the possibility to do something before or after a Methodinvocation. For this we have the \n***PreAction*** and ***PostAction***. The Actions are executed in the order they are added to the Proxy.\n\n```java\n    final Service service = DynamicProxyBuilder\n        .createBuilder(Service.class, new ServiceImpl())\n        .addIPreAction((original, method, args1) -\u003e out.println(\"001 = \" + method.getName()))\n        .addIPreAction((original, method, args1) -\u003e out.println(\"002 = \" + method.getName()))\n        .addIPreAction((original, method, args1) -\u003e out.println(\"003 = \" + method.getName()))\n        .build();\n```\n\nA ***VirtualProxy*** with ***PreActions*** will lead to the execution of all ***PreActions*** before the real Subject will be created. \n\n```java\n    final Service service = DynamicProxyBuilder\n        .createBuilder(Service.class, ServiceImpl.class, CreationStrategy.SOME_DUPLICATES)\n        .addIPreAction((original, method, args1) -\u003e out.println(\"001 = \" + method.getName()))\n        .addIPreAction((original, method, args1) -\u003e out.println(\"002 = \" + method.getName()))\n        .addIPreAction((original, method, args1) -\u003e out.println(\"003 = \" + method.getName()))\n        .build();\n```\n\nIf you combine it with a ***SecurityVirtualProxy*** with ***PreActions*** the Security-Rule will be invoked first.\n\n```java\n    final Service service = DynamicProxyBuilder\n        .createBuilder(Service.class, ServiceImpl.class, CreationStrategy.SOME_DUPLICATES)\n        .addIPreAction((original, method, args1) -\u003e out.println(\"001 = \" + method.getName()))\n        .addIPreAction((original, method, args1) -\u003e out.println(\"002 = \" + method.getName()))\n        .addIPreAction((original, method, args1) -\u003e out.println(\"003 = \" + method.getName()))\n        .addSecurityRule(() -\u003e {\n          out.println(\"sec 001\");\n          return true;\n        })\n        .build();\n```\n\n## CreationStrategies\nWith the ***CreationStrategies*** you can choose what will be the right way of synchronization for you if you are using ***VirtualProxies***. You can implement some other by yourself, if needed. With ***CreationStrategies*** you can do different things. Not only the creation of one Element is possible, you can e.g. create a pool of instances used randomly or you can do something like ***MethodScoped***. \n\n### MethodScoped\nThis ***CreationStrategy*** will create for every method invocation a new instance.\n\n```java\npublic class ServiceStrategyFactoryMethodScoped\u003cT\u003e implements ServiceStrategyFactory\u003cT\u003e {\n\n  @Override\n  public synchronized T realSubject(ServiceFactory\u003cT\u003e factory) {\n    return factory.createInstance();\n  }\n}\n```\n\n\n### NONE\nIf you choose nothing or ***CreationStrategy.NONE*** you will get the ***NotThreadSafe*** version.\n\n```java\npublic class ServiceStrategyFactoryNotThreadSafe\u003cT\u003e implements ServiceStrategyFactory\u003cT\u003e {\n\n  private T service;\n\n  @Override\n  public T realSubject(ServiceFactory\u003cT\u003e factory) {\n    if (service == null) {\n      service = factory.createInstance();\n    }\n    return service;\n  }\n\n}\n```\n\n### SomeDuplicates\n\n```java\npublic class ServiceStrategyFactorySomeDuplicates\u003cT\u003e implements ServiceStrategyFactory\u003cT\u003e {\n  private final AtomicReference\u003cT\u003e ref = new AtomicReference\u003c\u003e();\n\n  @Override\n  public T realSubject(ServiceFactory\u003cT\u003e factory) {\n\n    T service = ref.get();\n    if (service == null) {\n      service = factory.createInstance();\n      if (!ref.compareAndSet(null, service)) {\n        service = ref.get();\n      }\n    }\n    return service;\n  }\n}\n```\n\n### Synchronized\n\n```java\npublic class ServiceStrategyFactorySynchronized\u003cT\u003e implements ServiceStrategyFactory\u003cT\u003e {\n\n  private T service;\n\n  @Override\n  public synchronized T realSubject(ServiceFactory\u003cT\u003e factory) {\n    if (service == null) {\n      service = factory.createInstance();\n    }\n    return service;\n  }\n}\n```\n\n### NoDuplicates\n\n```java\npublic class ServiceStrategyFactoryNoDuplicates\u003cT\u003e implements ServiceStrategyFactory\u003cT\u003e {\n\n  private final Lock initializationLock = new ReentrantLock();\n  private volatile T realSubject;\n\n  @Override\n  public T realSubject(ServiceFactory\u003cT\u003e factory) {\n    T result = realSubject;\n    if (result == null) {\n      initializationLock.lock();\n      try {\n        result = realSubject;\n        if (result == null) {\n          result = realSubject = factory.createInstance();\n        }\n      } finally {\n        initializationLock.unlock();\n      }\n    }\n    return result;\n  }\n}\n```\n\n# Object Adapter\nIn this section we want to describe the ObjectAdapter Pattern that is realized in this module.\nWe can use a dynamic and a static version of the ***ObjectAdapter*** Pattern. The dynamic version is based on the DynamicProxy from jdk1.3 and the static version is purely generated via Annotation Processing. \n\n## DynamicObjectAdapter\nIf you want to use the ***DynamicObjectAdapter*** you need at leaset one Interface you can cast to. To create the ***DynamicObjectAdapter*** you can use the Annotation ***@DynamicObjectAdapterBuilder***. This will create via Annotation Processing the ***DynamicObjectAdapter*** and the corresponding ***Builder*** that you can use for convenience and type safety. Let´s assume you have the following interface ***Service***:\n\n\n```java\n@DynamicObjectAdapterBuilder\npublic interface Service {\n  String doWork(String txt);\n  String doMoreWorkA(String txt);\n  String doMoreWorkB(String txt);\n  String doMoreWorkC(String txt);\n  String doMoreWorkD(String txt);\n}\n``` \n\nWith the Annotation we are generating the corresponding parts, used for the typesafe generated DynamicObjectAdapterBuilder.\nYou will get a FunctionalInterface for every Method declared in your interface, and an typed InvocationHandler and the Builder itself. \n\nTo use the ***DynamicObjectAdapter*** you can do the following:\n\n```java\n    final Service service = ServiceAdapterBuilder\n        .newBuilder()\n        .setOriginal(new ServiceImpl())\n        .withDoWork(new ServiceMethodDoWork() {\n          @Override\n          public String doWork(final String txt) {\n            return \"mocked\";\n          }\n        })\n        .withDoMoreWorkC(new ServiceMethodDoMoreWorkC() {\n          @Override\n          public String doMoreWorkC(final String txt) {\n            return \"mocked again\";\n          }\n        })\n        .buildForTarget(Service.class);\n\n```\n\nAlso you can use the Lambda-Expressions for this. So your code will be shorter.\n```java\n    final Service serviceJDK8 = ServiceAdapterBuilder\n        .newBuilder()\n        .setOriginal(new ServiceImpl())\n        .withDoWork(txt -\u003e \"mocked\")\n        .withDoMoreWorkC(txt -\u003e \"mocked again\")\n        .buildForTarget(Service.class);\n``` \n\nYou can use this for mocking too, if you want. For this you could adapt the methods you need and set the original to null.\n\n```java\n    final Service serviceJDK8Mock = ServiceAdapterBuilder\n        .newBuilder()\n        .setOriginal(null)\n        .withDoWork(txt -\u003e \"mocked\")\n        .withDoMoreWorkC(txt -\u003e \"mocked again\")\n        .buildForTarget(Service.class);\n```\n\nIf you can not use AnnotationProcessing, you are able to use the DynamicObjectAdapter itself.  \n\n```java\n    final ExtendedInvocationHandler\u003cService\u003e extendedInvocationHandler\n        = new ExtendedInvocationHandler\u003cService\u003e() { };\n\n    extendedInvocationHandler.addAdapter(new Object() {\n      public String doMoreWorkB(String txt) {\n        return \"mocked\";\n      }\n    });\n\n    final AdapterBuilder\u003cService\u003e adapterBuilder = new AdapterBuilder\u003cService\u003e() {\n      @Override\n      protected ExtendedInvocationHandler\u003cService\u003e getInvocationHandler() {\n        return extendedInvocationHandler;\n      }\n    };\n\n    final Service service = adapterBuilder.buildForTarget(Service.class);\n```\n\nOr if you want to write it even more compact..\n\n```java\nfinal Service service = new AdapterBuilder\u003cService\u003e() {\n      protected ExtendedInvocationHandler\u003cService\u003e getInvocationHandler() {\n        return new ExtendedInvocationHandler\u003cService\u003e() {\n          {\n            addAdapter(new Object() {\n              public String doMoreWorkB(String txt) {\n                return \"mocked\";\n              }\n            });\n          }\n        };\n      }\n    }\n    .buildForTarget(Service.class);\n```\n\n## StaticObjectAdapter\nIf you want, you can use the static ObjectAdapter nearly in the same way. But here you will get no Builder. You only will get the functional interfaces and the Adapter itself. Add the Annotation ***@StaticObjectAdapter*** to an Interface or Class.\n\n```java\n@StaticObjectAdapter\npublic interface Service {\n  String doWork(String txt);\n  String doMoreWorkA(String txt);\n  String doMoreWorkB(String txt);\n  String doMoreWorkC(String txt);\n  String doMoreWorkD(String txt);\n}\n```\n\nAfter a ***mvn clean compile*** you will get the Functionalinterfaces and the StaticObjectAdapter itself.\n\n\n```java\nfinal Service service = new ServiceStaticObjectAdapter()\n        .withService(new ServiceImpl())\n        .withServiceMethodDoMoreWorkC(new ServiceMethodDoMoreWorkC() {\n          @Override\n          public String doMoreWorkC(final String txt) {\n            return \"mocked\";\n          }\n        })\n        .withServiceMethodDoMoreWorkD(new ServiceMethodDoMoreWorkD() {\n          @Override\n          public String doMoreWorkD(final String txt) {\n            return \"mocked\";\n          }\n        });\n\n```\n\nAnd here again, you can write it with short Lambda-syntax:\n\n```java\nfinal Service service = new ServiceStaticObjectAdapter()\n        .withService(new ServiceImpl())\n        .withServiceMethodDoMoreWorkC(txt -\u003e \"mocked\")\n        .withServiceMethodDoMoreWorkD(txt -\u003e \"mocked\");\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsvenruppert%2Fproxybuilder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsvenruppert%2Fproxybuilder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsvenruppert%2Fproxybuilder/lists"}