blog

マジック・バリューの拒否, java もメソッドに渡すことができる, mybatisPlus pass メソッド

背景\n\n\n\nパッケージ;\nインポート ;...

Jun 3, 2020 · 4 min. read
シェア

背景

関連コード

FnConverter

package com.example.demo.bean;
import com.example.demo.entity.ValidatedRequestVO;
/**
 * 
 * @description
 * @date 7/ 7:20 PM
 */
public class FnConverter<F, T> {
 /**
 * 入力メソッドがフィールド名を返す
 *
 * @param fn  
 * @return  
 * 
 * @date 7/ 7:32 PM
 */
 public String fnToFieldName(IFn<F, T> fn) {
 return Reflections.fnToFieldName(fn);
 }
 /**
 * メソッドを渡してメソッド名を返す
 *
 * @param fn  
 * @return  
 * 
 * @date 7/ 7:32 PM
 */
 public String fnToFnName(IFn<F, T> fn) {
 return Reflections.fnToFnName(fn);
 }
 /**
 * 受信メソッドの戻り値アノテーション
 *
 * @param fn  
 * @return mongo 
 * 
 * @date 7/ 7:32 PM
 */
 public String fnToMongoName(IFn<F, T> fn) {
 return Reflections.fnToMongoName(fn);
 }
 public static void main(String[] args) {
 FnConverter<ValidatedRequestVO, Object> fnConverter = new FnConverter();
 String fieldName = fnConverter.fnToFieldName(ValidatedRequestVO::getStr);
 System.out.println("フィールド名" + fieldName);
 String fnName = fnConverter.fnToFnName(ValidatedRequestVO::getStr);
 System.out.println("メソッド名" + fnName);
 FnConverter<String, Object> fnConverter2 = new FnConverter();
 String fieldName2 = fnConverter2.fnToFieldName(new ValidatedRequestVO()::setStr);
 System.out.println("フィールド名" + fieldName2);
 String fnName2 = fnConverter2.fnToFnName(new ValidatedRequestVO()::setStr);
 System.out.println("メソッド名" + fnName2);
 FnConverter<ValidatedRequestVO, Object> fnConverter3 = new FnConverter();
 String fieldName3 = fnConverter3.fnToMongoName(ValidatedRequestVO::getStartDate);
 System.out.println("フィールド名" + fieldName3);
 }
}

IFn

package com.example.demo.bean;
import java.io.Serializable;
/**
 * F 入力型、戻り値型
 * 
 */
@FunctionalInterface
public interface IFn<F, T> extends Serializable {
 T apply(F source);
}

リフレクションズ

package com.example.demo.bean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.mongodb.core.mapping.Field;
import java.beans.Introspector;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
/**
 * メソッドを渡した後にロジックを実装する
 *
 * 
 * @date 7/ 7:20 PM
 */
@Slf4j
public class Reflections {
 private Reflections() {
 }
 public static String fnToFieldName(IFn fn) {
 try {
 Method method = fn.getClass().getDeclaredMethod("writeReplace");
 method.setAccessible(Boolean.TRUE);
 SerializedLambda serializedLambda = (SerializedLambda) method.invoke(fn);
 String getter = serializedLambda.getImplMethodName();
 String fieldName = "";
 if (getter.startsWith("get")) {
 fieldName = Introspector.decapitalize(getter.replace("get", ""));
 } else {
 fieldName = Introspector.decapitalize(getter.replace("set", ""));
 }
 return fieldName;
 } catch (ReflectiveOperationException e) {
 log.warn(String.format("%s:%s",
 Thread.currentThread().getStackTrace()[1].getMethodName(), e.getMessage()), e);
 }
 return "";
 }
 public static String fnToFnName(IFn fn) {
 try {
 Method method = fn.getClass().getDeclaredMethod("writeReplace");
 method.setAccessible(Boolean.TRUE);
 SerializedLambda serializedLambda = (SerializedLambda) method.invoke(fn);
 return serializedLambda.getImplMethodName();
 } catch (ReflectiveOperationException e) {
 log.warn(String.format("%s:%s",
 Thread.currentThread().getStackTrace()[1].getMethodName(), e.getMessage()), e);
 }
 return "";
 }
 public static String fnToMongoName(IFn fn) {
 try {
 Method method = fn.getClass().getDeclaredMethod("writeReplace");
 method.setAccessible(Boolean.TRUE);
 SerializedLambda serializedLambda = (SerializedLambda) method.invoke(fn);
 String getter = serializedLambda.getImplMethodName();
 String fieldName = "";
 if (getter.startsWith("get")) {
 fieldName = Introspector.decapitalize(getter.replace("get", ""));
 } else {
 fieldName = Introspector.decapitalize(getter.replace("set", ""));
 }
 Field field = Class.forName(serializedLambda.getImplClass().replace("/", ".")).getDeclaredField(fieldName).getAnnotation(Field.class);
 return field == null ? fieldName : field.value();
 } catch (ReflectiveOperationException e) {
 log.warn(String.format("%s:%s",
 Thread.currentThread().getStackTrace()[1].getMethodName(), e.getMessage()), e);
 }
 return "";
 }
}

アプリケーション例

  1. ビデオで紹介されているように、メソッド/フィールドを取ることができるアノテーション
  2. 反射を利用した擬似プロキシ
  3. 最も一般的なアプリケーションはmybatisPlusで、SQLを変更することなく、必要なフィールドや不要なフィールドを動的に渡すことができ、パフォーマンスを最適化できます。

Read next

V8についての深い議論

ほとんどのフロントエンド開発者は、V8というバズワードについて話してきました。 その人気の多くは、パフォーマンスを新しいレベルに引き上げるという事実によるものです。 確かにV8は速いです。 しかし、V8はどのようにして魔法を使うのでしょうか? 公式ドキュメントには「V8はGoogleのオープンソース高性能JavaSc...

Jun 3, 2020 · 7 min read