Javaでプロキシクラスを動的に生成する

おそらく、すべてのJava開発者は遅かれ早かれプロキシクラスを使用する必要があります。

猫の下には、JDKプロキシ、cglib、javassist、およびバイトバディを使用して作成された簡単な例があります。







画像






最も簡単なタスクを設定します。









実験するユーザークラス。
public class User implements IUser { private final String name; public User() { this(null); } public User(String name) { this.name = name; } @Override public String getName() { return name; } }
      
      





1標準ツール-JDKプロキシ



輸入品
 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy;
      
      





 User user = new User(""); InvocationHandler handler = (proxy, method, args) -> { if(method.getName().equals("getName")){ return ((String)method.invoke(user, args)).toUpperCase(); } return method.invoke(user, args); }; IUser userProxy = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(), User.class.getInterfaces(), handler); assertEquals("", userProxy.getName());
      
      





欠点は、Userクラスのインターフェイスを実装するプロキシクラスしか作成できないことです。 つまり、ユーザーでプロキシクラスをキャストすることは不可能です







2 cglib



輸入品
 import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor;
      
      





 User user = new User(""); MethodInterceptor handler = (obj, method , args, proxy) -> { if(method.getName().equals("getName")){ return ((String)proxy.invoke(user, args)).toUpperCase() ; } return proxy.invoke(user, args); }; User userProxy = (User) Enhancer.create(User.class, handler); assertEquals("", userProxy.getName());
      
      





3 javassist



輸入品
 import javassist.util.proxy.MethodHandler; import javassist.util.proxy.ProxyFactory; import javassist.util.proxy.ProxyObject;
      
      





 User user = new User(""); MethodHandler handler = (self, overridden, forwarder, args) -> { if(overridden.getName().equals("getName")){ return ((String)overridden.invoke(user, args)).toUpperCase(); } return overridden.invoke(user, args); }; ProxyFactory factory = new ProxyFactory(); factory.setSuperclass(User.class); Object instance = factory.createClass().newInstance(); ((ProxyObject) instance).setHandler(handler); User userProxy = (User) instance; assertEquals("", userProxy.getName());
      
      





4バイトバディ



輸入品
 import net.bytebuddy.ByteBuddy; import net.bytebuddy.implementation.MethodDelegation; import static net.bytebuddy.matcher.ElementMatchers.named;
      
      





 User user = new User(""); User userProxy = new ByteBuddy() .subclass(User.class) .method(named("getName")) .intercept(MethodDelegation.to(new MyInterceptor(user))) .make() .load(User.class.getClassLoader()) .getLoaded() .newInstance(); assertEquals("", userProxy.getName());
      
      





MyInterceptor
 public class MyInterceptor { User user; public MyInterceptor(User user) { this.user = user; } public String getName() { return user.getName().toUpperCase(); } }
      
      





生産性、シンプルさ、現代性-自分のプロジェクトにより適したものを選択してください。







パフォーマンスを比較するために、記事を読むことを提案します

4つのJavaランタイムコードジェネレーターのパフォーマンスのテスト:cglib、javassist、JDKプロキシー、Byte Buddy








All Articles