1

ポイントカットを使用して、特定のメソッドで を識別し、それにAPI メソッドCriteriaを適用する、アスペクト指向の注釈 (またはその他の機能) を使用してページネーションを休止状態にする既知のアプローチはありますか?setFirstResultssetMaxResults

たとえば、休止状態のGenericDao実装で次のようにページネーションを適用したいと思います。

@Paginate
public List<T> filter(Set<Criterion> filter, Map<String, String> alias){
    Criteria criteria = session.createCriteria(type.class);
    fillCriteria(criteria, filter, alias);
    return criteria.list();
}

そして、@Paginate注釈は通話中に適用さsetFirstResultssetMaxResultsますcriteria.list()。これは可能ですか?

注:@Paginate私が使いたいものの例です。

4

1 に答える 1

1

はい、 AspectJ経由でこれを行うことができます。

以下は、自己一貫性のあるスタンドアロンのコード サンプルです。クラスとアスペクトをコピーして貼り付けて実行するだけです。私は元の Hibernate クラスを使用していませんが、私は Hibernate ユーザーではなく、これを汎用的な回答にしたいため、ダミーの代替品をいくつか使用しています。

ダミーの休止状態のようなインターフェイスとクラス:

package de.scrum_master.app;

public interface Criterion {}
package de.scrum_master.app;

public class MyCriterion implements Criterion {
    private String criterion;

    public MyCriterion(String criterion) {
        this.criterion = criterion;
    }

    @Override
    public String toString() {
        return "MyCriterion [criterion=" + criterion + "]";
    }
}
package de.scrum_master.app;

import java.util.List;

public interface Criteria {
    Criteria add(Criterion criterion);
    List list();
    Criteria setFirstResult(int firstResult);
    Criteria setMaxResults(int maxResults);
}
package de.scrum_master.app;

import java.util.LinkedList;
import java.util.List;

public class MyCriteria implements Criteria {
    private List<Criterion> criteria = new LinkedList<>();

    @Override
    public Criteria add(Criterion criterion) {
        criteria.add(criterion);
        return this;
    }

    @Override
    public List list() {
        return new LinkedList();
    }

    @Override
    public Criteria setFirstResult(int firstResult) {
        add(new MyCriterion("first result " + firstResult));
        return this;
    }

    @Override
    public Criteria setMaxResults(int maxResults) {
        add(new MyCriterion("max results " + maxResults));
        return this;
    }

    @Override
    public String toString() {
        return "MyCriteria [criteria=" + criteria + "]";
    }
}

ご覧のとおり、メソッドsetFirstResult(..)と内部リストsetMaxResults(..)を介して特別な基準を追加します。add(..)後でアスペクトの効果を説明するためにこれを行いました。

ページネーションの注釈:

package de.scrum_master.app;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Paginate {}

ドライバー アプリケーション:

package de.scrum_master.app;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Application {
    @Paginate
    public List filter(Set<Criterion> filter, Map<String, String> alias) {
        Criteria criteria = new MyCriteria();
        for (Criterion criterion : filter)
            criteria.add(criterion);
        return criteria.list();
    }

    public static void main(String[] args) {
        Set<Criterion> filterCriteria = new HashSet<>();
        filterCriteria.add(new MyCriterion("where"));
        filterCriteria.add(new MyCriterion("group by"));
        new Application().filter(filterCriteria, null);
    }
}

@Paginateアプリケーションには、サンプル コードと同様のことを行う、 で注釈が付けられたメソッドが含まれています。ただし、ページネーション メソッドは呼び出されません。これは、次の側面によって行われます。

ページネーションの側面:

package de.scrum_master.aspect;

import java.util.List;
import de.scrum_master.app.Paginate;
import de.scrum_master.app.Criteria;

public aspect PaginationAspect {
    Object around(Criteria criteria) : 
        call(public List Criteria+.list())  &&
        cflow(execution(@Paginate * *(..))) &&
        target(criteria)
    {
        System.out.println(thisJoinPoint);
        System.out.println("Original criteria: " + criteria);
        criteria.setFirstResult(5);
        criteria.setMaxResults(10);
        System.out.println("Modified criteria: " + criteria);
        return proceed(criteria);
    }
}

Criteria+.list()ポイントカットは(インクルード サブクラス)への呼び出しをインターセプトしますが、によって注釈が付けられた実行中のメソッド+の制御フロー ( ) で発行された場合のみです。呼び出しターゲットは、そのポイントカットにバインドされたアドバイス メソッドで使用するためにパラメーターにバインドされます。ページネーション メソッドを呼び出したいので、call ターゲットへの参照が必要です。これがアドバイスの動作であり、コンソール出力によって明確に示されています。cflow()@PaginateCriteria criteria

コンソール出力:

call(List de.scrum_master.app.Criteria.list())
Original criteria: MyCriteria [criteria=[MyCriterion [criterion=group by], MyCriterion [criterion=where]]]
Modified criteria: MyCriteria [criteria=[MyCriterion [criterion=group by], MyCriterion [criterion=where], MyCriterion [criterion=first result 5], MyCriterion [criterion=max results 10]]]

楽しみ!

于 2014-10-21T14:26:09.703 に答える