@ReferencedResource
カスタム注釈または別の注釈で注釈が付けられた wicket コンポーネントの大規模なライブラリがあり、複数の注釈を許可するパラメーター@ReferencedResources
があります。ReferencedResouce[] value()
サンプル コード スニペットを次に示します。
@ReferencedResources({
@ReferencedResource(value = Libraries.MOO_TOOLS, type = ResourceType.JAVASCRIPT),
@ReferencedResource(value = "behaviors/promoteSelectOptions", type = ResourceType.JAVASCRIPT) })
public class PromoteSelectOptionsBehavior extends AbstractBehavior{
...
}
ここまでは、aptを使用して参照先のリソースが実際に存在することを確認しました。例えば
@ReferencedResource(value = "behaviors/promoteSelectOptions",
type = ResourceType.JAVASCRIPT)
js/behaviors/promoteSelectOptions.js
ファイルがクラスパスで見つからない限り、コンパイルは失敗します。この部分はうまく機能します。
現在、私は DRY のファンでもあり、同じアノテーションを使用して、オブジェクトが作成されたときに実際にリソースをオブジェクトに注入したいと考えています。AspectJ を使用して、この一部を実装しました。
注釈付きオブジェクトは、常にComponentまたはAbstractBehaviorのいずれかのインスタンスです。
コンポーネントの場合は簡単で、コンストラクターの後に一致させるだけです。これを行うアドバイスは次のとおりです。
pointcut singleAnnotation() : @within(ReferencedResource);
pointcut multiAnnotation() : @within(ReferencedResources);
after() : execution(Component+.new(..)) && (singleAnnotation() || multiAnnotation()){
final Component component = (Component) thisJoinPoint.getTarget();
final Collection<ReferencedResource> resourceAnnotations =
// gather annotations from cache
this.getResourceAnnotations(component.getClass());
for(final ReferencedResource annotation : resourceAnnotations){
// helper utility that handles the creation of statements like
// component.add(JavascriptPackageResource.getHeaderContribution(path))
this.resourceInjector.inject(component, annotation);
}
}
ただし、動作の場合は、動作自体ではなく、応答にリソースを添付する必要があります。私が使用するポイントカットは次のとおりです。
pointcut renderHead(IHeaderResponse response) :
execution(* org.apache.wicket.behavior.AbstractBehavior+.renderHead(*))
&& args(response);
そして、ここにアドバイスがあります:
before(final IHeaderResponse response) :
renderHead(response) && (multiAnnotation() || singleAnnotation()) {
final Collection<ReferencedResource> resourceAnnotations =
this.getResourceAnnotations(thisJoinPoint.getTarget().getClass());
for(final ReferencedResource resource : resourceAnnotations){
this.resourceInjector.inject(response, resource);
}
}
これは、クラスがrenderHead(response)メソッドをオーバーライドする場合にもうまく機能しますが、多くの場合、スーパー クラスは基本機能を既に実装しているのに対し、子クラスはいくつかの構成を追加するだけであるため、必要ありません。したがって、1 つの解決策は、これらのクラスに次のようなメソッドを定義させることです。
@Override
public void renderHead(IHeaderResponse response){
super.renderHead(response);
}
これはデッド コードであるため、私はこれを嫌いますが、現在これが唯一の有効なオプションであるため、他の解決策を探しています。
編集:
APT と sun javac 呼び出しを使用して、実用的なソリューションを作成しました。ただし、これは次の問題につながります。maven を使用して同じプロジェクトで APT と AspectJ を実行することです。
とにかく、時間ができ次第、この質問 (またはその一部) への回答を投稿します。