cglib

4996 ワード

CGlibって何?CGlibは強力で、高性能で、高品質のCode生成クラスライブラリです.実行中にJavaクラスを拡張し、Javaインタフェースを実装できます.もちろんこれらの実際の機能はasmが提供しているのですが、asmは何ですか?Javaバイトコードの操作フレームワークは、具体的には何なのか、インターネットで調べることができます.結局、ここで議論するのはcglibです.cglibはasmをカプセル化し、asmの操作を簡素化し、運行期間中に新しいclassを動的に生成することを実現しました.皆さんはまだその強さを感じていないかもしれませんが、今すぐ教えてあげます.実際にCGlibはspring aopに最下位の実装を提供した.hibernateのためにcglibを使用してVO/PO(インタフェースレイヤオブジェクト)を動的に生成します.次に、CGlibがCGlibを体験する具体的な事例を見てみましょう.*CGlib 2.13*ASM 2.23は、簡単に説明するcglibの応用例である.仮想シーンをシミュレートし、テーブルの操作をシミュレートします.1.まず、テーブルにCRUDメソッドを提供します.次に、Table操作に対するDAOクラスを作成します.
public class TableDAO {
	public void create(){
		System.out.println("create() is running !");
	}
	public void query(){
		System.out.println("query() is running !");
	}
	public void update(){
		System.out.println("update() is running !");
	}
	public void delete(){
		System.out.println("delete() is running !");
	}
}

OK、それはjavaBeanであり、CRUDメソッドのjavaBeanを提供しています.次に、DAOインスタンスを生成するためのDAOファクトリを作成します.
public class TableDAOFactory {
	private static TableDAO tDao = new TableDAO();
	public static TableDAO getInstance(){
		return tDao;
	}
}

次に、CRUDメソッドを呼び出すクライアントを作成します.
public class Client {

	public static void main(String[] args) {
		TableDAO tableDao = TableDAOFactory.getInstance();
		doMethod(tableDao);
	}
	public static void doMethod(TableDAO dao){
		dao.create();
		dao.query();
		dao.update();
		dao.delete();
	}
}

OK、完了、CRUDメソッドが完全に呼び出されました.もちろんここにはCGlibの内容はありません.問題はこんなに簡単に終わることはありません.新しい需要が来ました.2.変化に伴い、Bossはこれらの方法をユーザーに開放することができず、「張三」だけが使用する権利があることを教えてくれた.あ~!どうすればいいのか、私たちはすべての方法で判断しなければならないのだろうか.そうするのはあまりにもそうでしょう.そう、Proxyが最善の解決策かもしれません.jdkのエージェントで解決できます.さあ、改造に着手しましょう.などjdkのエージェントはインタフェースを実現する必要があります.そうすれば、私たちのdaoクラスは変更する必要があります.daoを変更したくないし、エージェントを使う以上、CGlibを出してください.権限検証のメソッドブロッキングを追加するだけです.
public class AuthProxy implements MethodInterceptor {
	private String name ;
	//      
	public AuthProxy(String name){
		this.name = name;
	}
	public Object intercept(Object arg0, Method arg1, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		//      
		if(!"  ".equals(name)){
			System.out.println("     !");
			return null;
		}
		return arg3.invokeSuper(arg0, arg2);
	}
}

もちろん、daoファクトリを変更することを忘れてはいけません.エージェントを使用したインスタンス生成方法を提供します.
public static TableDAO getAuthInstance(AuthProxy authProxy){
 Enhancer en = new Enhancer();
 //    
 en.setSuperclass(TableDAO.class);
 en.setCallback(authProxy);
 //      
 return (TableDAO)en.create();
}

クライアントの実装を見ることができます.異なるユーザーの権限を検証するための2つの方法が追加されました.
public static void haveAuth(){
	TableDAO tDao = TableDAOFactory.getAuthInstance(new AuthProxy("  "));
	doMethod(tDao);
}
public static void haveNoAuth(){
	TableDAO tDao = TableDAOFactory.getAuthInstance(new AuthProxy("  "));
	doMethod(tDao);
}

OK、「張三」の正常な実行、「李四」の実行はありません.見えますか?简単なaopがこのように実现してまさかこのように终わったのですか?3.ボスはまた訓話に来た.だめだ.だめだ.今は「張三」以外の人は使えない.今はそんなことはできない.彼らはすべて私に反映しに来て、オープンクエリー機能を使用しなければなりません.ははは、今は私たちを倒すことができません.CGlibを使っているからです.もちろん最も簡単な方法は、私たちの方法ブロックを修正することですが、論理を複雑にし、メンテナンスに不利になります.CGlibはメソッドフィルタ(CallbackFilter)を提供してくれて、CallbackFilteはエージェントのクラスの中で異なるメソッドが、どのブロッキングによってブロックされているかを明確に示すことができます.次にqueryメソッドをフィルタするためのフィルタを作成します.
public class AuthProxyFilter implements CallbackFilter{
	public int accept(Method arg0) {
		if(!"query".equalsIgnoreCase(arg0.getName()))
			return 0;
		return 1;
	}

}

OK、return 0 or 1に戸惑うかもしれませんが、使うときに説明してくれるので、もちろん以下に使います.工場にフィルタを用いたインスタンス生成方法を追加しました.
public static TableDAO getAuthInstanceByFilter(AuthProxy authProxy){
	Enhancer en = new Enhancer();
	en.setSuperclass(TableDAO.class);
	en.setCallbacks(new Callback[]{authProxy,NoOp.INSTANCE});
	en.setCallbackFilter(new AuthProxyFilter());
	return (TableDAO)en.create();
}

NoOp.INSTANCEはCGlibが提供する実際には何の操作もないブロックであり、秩序があるsetCallbacksで使用されるブロックが定義されているのを見ましたか.必ずCallbackFilterの中の順番と一致しなければなりません.分かりましたか.上のreturnが返す順番です.すなわちqueryメソッドを呼び出すとNoOp.INSTANCEを用いてブロックする.クライアントコードを見てみましょう.
public static void haveAuthByFilter(){
	TableDAO tDao = TableDAOFactory.getAuthInstanceByFilter(new AuthProxy("  "));
	doMethod(tDao);

	tDao = TableDAOFactory.getAuthInstanceByFilter(new AuthProxy("  "));
	doMethod(tDao);
}

OK、今では「李四」もqueryメソッドを使用することができますが、他のメソッドには権限がありません.ハハ、もちろんこのエージェントの実装には侵入性はなく、daoにインタフェースを強制する必要はありません.