アクセスできないモデルを作成するにはどうすればよいですか

ああ悲しい

私は昨日の次のインタビューに座って、 javaxが うんざり していることを悲しんでいた 。そして、ソースのないJavaモデルへのJSONでのシリアライゼーションを固定しようとして苦しんでいる申請者の悲しい話を聞いた。 彼の試みの気分は私の気分を改善しませんでした。

彼とは違って、Groovyについて知っているからです。

この投稿はほぼ昨日の続きです。 彼らはうさぎの袋を殺したいと思っています。

  1. 実際のGroovyメタプログラミングの例を表示する
  2. メタクラスを操作するためのもう少し洗練された方法を示します
  3. Groovyでjson-libの動作を表示する
  4. 貧しい人々のための依存関係管理について話す




goose javaには何がありますか



Javaで記述されたJavaBeansのモデルがあり、例として、ソートがないと仮定します。 また、楽しみのために、このモデルには共通のインターフェースやスーパークラスがなく、このモデルがまとめるものはすべてパッケージであると仮定します。したがって、ポリモーフィズムは忘れてください。 たとえば、モデルには既に2つのクラス(model.Clockとmodel.Radioがあり、どちらもObjectを拡張し、それらには2つのフィールドがあります)のひもとプリミティブがあるとします。



何が必要ですか?



この記事の終わりまでにパスするテストは次のとおりです。

import model.Radio import service.Service Radio radio = new Radio() radio.frequency = 91.2 radio.volume = 20 def json = radio.toJson() assert json == '{"frequency":91.2,"volume":20}' Radio radioClone = Radio.parseJson(json) assert radioClone == radio try { new Service().toJson() assert false } catch (MissingMethodException e){}
      
      







当然、toJson()メソッドもparseJson()メソッドもRadioクラスには存在しないため、テストは「groovy.lang.MissingMethodException:メソッドのシグネチャなし:model.Radio.toJson()が引数タイプに適用可能」でクラッシュします。 ()値:[] "。

最後にtryで確認します-パッケージモデルに関連していないServiceクラスには、シャーマニズムの結果としてtoJsonメソッドとparseJsonメソッドがありません。



誰が責任を負いますか?



もちろん、(少なくとも昨日から)メソッドを追加および置換できるクラスのMetaClassを使用することを既に知っています。 そのため、パッケージモデルのすべてのクラスのMetaClassにtoJson()およびparseJson()メソッドを追加する必要があります。 そしてどうやって? Javaでは、これはすべて悪いことです。パッケージからクラスのリストを取得することはできません。 まあ、つまり、それは可能ですが、必ずしもそうとは限りませんが、常にではなく、jar、および一連の制限とコードシートからのみ可能です。 これは私たちの方法ではありません。 私たちはGroovyです。

Groovyは間違いなくクラスローディングに食い込んでいます。 たとえば、MetaClassを作成します。 そして、私たちはまだ彼らとシャーマンをプレイするつもりなので、それらを作成するプロセスに没頭することができます!

groovy.lang.MetaClassRegistryクラスで、MetaClassを作成するHandler作成コードを確認します(コードを少し簡略化しましたが、ポイントは次のとおりです)。

  try { Class customHandle = Class.forName("groovy.runtime.metaclass.CustomMetaClassCreationHandle"); this.handle = customHandle.newInstance(); } catch (ClassNotFoundException e) { // custom handler,    this.handle = new MetaClassCreationHandle(); }
      
      





「シャーロック、それは何?」

「それは初歩的だ、ワトソン。」 これは拡張ポイントの1つであり、独自のMetaClassCreationHandleを記述して、新しいメソッドとジェイソンを使用して独自のMetaClassを作成できます。

ここではすべてが明確で、Groovyは「groovy.runtime.metaclass.CustomMetaClassCreationHandle」というクラスを探しています。これを彼に渡します。

 public class CustomMetaClassCreationHandle extends MetaClassRegistry.MetaClassCreationHandle { protected MetaClass createNormalMetaClass(Class theClass, MetaClassRegistry registry) { Package thePackage = theClass.getPackage(); if (thePackage != null && thePackage.getName().equals("model")) { return new Jsonizer(theClass); } else { return super.createNormalMetaClass(theClass, registry); } } }
      
      





パッケージの場合-メタクラスを提供し、そうでない場合-ネイティブ。 私は考慮-オフセット。

奇抜なセミコロンに注意してください。 そうです、CustomMetaClassCreationHandleは、GroovyではなくJavaクラスである必要があります。これは、鶏と卵があるためです。Groovyクラスを作成するには、既に作成されているMetaClassCreationHandleが必要です。



残っているのは、独自のMetaClassを記述することです。このクラスでは、1つの通常の(インスタンス)メソッドと1つの静的メソッドを追加します。

ここでは、おそらく小さな作業計画の概要を説明する必要があります。

  1. ExpandoMetaClassから継承します(これはメソッドを追加できるものです)
  2. Json-lib thがこれをJSON文字列にシリアル化するtoJsonメソッドを追加します
  3. Json-lib thがjson文字列をオブジェクトにデシリアライズする静的parseJsonメソッドを追加します


そして、これが作業計画に関する質問と回答のリストです(キャンペーン、私はリストが好きです)



私たちは見ます:

(ユーザーをマークするための「犬」の新たに導入されたサポートは、注釈アナウンスメントコードを破るので、あなた自身が知っているものの代わりに「a」があります。まあ、あなたは理解しています。)

 groovy.lang.Grapes([ GrabResolver(name = 'rjo', root = 'http://repo.jfrog.org/artifactory/libs-releases'), Grab(group = 'net.sf.json-lib', module = 'json-lib', version = '2.4', classifier = 'jdk15')]) class Jsonizer extends ExpandoMetaClass { Jsonizer(Class theClass) { super(theClass) toJson << {-> fromObject(delegate).toString() } static.parseJson << {String json -> toBean(fromObject(json), theClass); } } }
      
      





まあ、一般的に利益。 テストに合格し、時計とラジオはメソッドを拡張しましたが、サービスはそうではありません。このプロセスを楽しんでください。



そうでなければ、結論も必要です。



  1. 「すでにあるものに触れることなく、そして/またはどこでも動作するようにここに固定することができる」と考えている場合、おそらくメタプログラミングを考えているでしょう。
  2. Javaメタプログラミングは、Groovyで行うのが最適です。
  3. Groovyには多くの拡張ポイントがありますので、探してみてください(見つからない場合はJIRAで機能を開いてください。次のバージョンでは間違いなく見つかります)。



All Articles