1)原始需求是任何人可以操作資訊的create,update,delete,query操作。
InfoManager.java--封裝對資訊的操作
public class InfoManager {
// 類比查詢操作
public void query() {
System.out.println( " query " );
}
// 類比建立操作
public void create() {
System.out.println( " create " );
}
// 類比更新操作
public void update() {
System.out.println( " update " );
}
// 類比刪除操作
public void delete() {
System.out.println( " delete " );
}
}
InfoManagerFactory.java--工廠類
public class InfoManagerFactory {
private static InfoManager manger = new InfoManager();
/**
* 建立原始的InfoManager
*
* @return
*/
public static InfoManager getInstance() {
return manger;
}
}
client.java--供用戶端調用
public class Client {
public static void main(String[] args) {
Client c = new Client();
c.anyonecanManager();
}
/**
* 類比:沒有任何許可權要求,任何人都可以操作
*/
public void anyonecanManager() {
System.out.println( " any one can do manager " );
InfoManager manager = InfoManagerFactory.getInstance();
doCRUD(manager);
separatorLine();
}
2)只有一個叫“maurice”的使用者登入,才允許對資訊進行create,update,delete,query的操作。
怎麼辦。難道在每個方法前,都加上一個許可權判斷嗎。這樣重複邏輯太多了,於是乎想到了Proxy(代理模式),但是原先的InfoManager也沒有實現介面,不能採用jdk的proxy。那麼cglib在這邊就要隆重登場。
一旦使用cgblig,只需要添加一個MethodInterceptor的類以及修改factory代碼就可以實現這個需求。
AuthProxy.java--許可權校正代理類
public class AuthProxy implements MethodInterceptor {
private String name; // 會員登入名稱
public AuthProxy(String name) {
this .name = name;
}
/**
* 許可權校正,如果會員名為:maurice,則有許可權做操作,否則提示沒有許可權
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
if ( ! " maurice " .equals( this .name)) {
System.out.println( " AuthProxy:you have no permits to do manager! " );
return null ;
}
return proxy.invokeSuper(obj, args);
}
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
}
InfoManagerFactory.java--代碼變動如下:
public class InfoManagerFactory {
/**
* 建立帶有許可權檢驗的InfoManager
*
* @param auth
* @return
*/
public static InfoManager getAuthInstance(AuthProxy auth) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(InfoManager. class );
enhancer.setCallback(auth);
return (InfoManager) enhancer.create();
}
}
client.java--代碼修改如下
public class Client {
public static void main(String[] args) {
Client c = new Client();
c.haveNoAuthManager();
c.haveAuthManager();
}
/**
* 類比:登入會員沒有許可權
*/
public void haveNoAuthManager() {
System.out.println( " the loginer's name is not maurice,so have no permits do manager " );
InfoManager noAuthManager = InfoManagerFactory.getAuthInstance( new AuthProxy( " maurice1 " ));
doCRUD(noAuthManager);
separatorLine();
}
/**
* 類比:登入會員有許可權
*/
public void haveAuthManager() {
System.out.println( " the loginer's name is maurice,so have permits do manager " );
InfoManager authManager = InfoManagerFactory.getAuthInstance( new AuthProxy( " maurice " ));
doCRUD(authManager);
separatorLine();
}
3)由於query功能使用者maurice才能使用,招來其他使用者的強烈的抱怨,所以許可權再次變更,只有create,update,delete,才需要許可權保護,query任何人都可以使用。
怎麼辦。採用AuthProxy,使得InfoManager中的所有方法都被代理,加上了許可權的判斷。當然,最容易想到的辦法,就是在AuthProxy的intercept的方法中再做下判斷,如果代理的method是query,不需要許可權驗證。這麼做,可以,但是一旦邏輯比較複雜的時候,intercept這個方法要做的事情會很多,邏輯會異常的複雜。
幸好,cglib還提供了CallbackFilter。使用CallbackFilter,可以明確表明,被代理的類(InfoManager)中不同的方法,被哪個攔截器(interceptor)攔截。
AuthProxyFilter.java public class AuthProxyFilter implements CallbackFilter {
private static final int AUTH_NEED = 0 ;
private static final int AUTH_NOT_NEED = 1 ;
} 這段代碼什麼意思。其中的accept方法的意思是說,如果代理的方法是query(),那麼使用第二個攔截器去攔截,如果代理的方法不是query(),那麼使用第一個攔截器去攔截。所以我們只要再寫一個攔截器,不做許可權校正就行了。(其實,cglib中的NoOp.INSTANCE就是一個空的攔截器,只要配置上這個就可以了。)
InfoManagerFactory.java--代碼修改如下:(配置不同的攔截器和filter)
public class InfoManagerFactory {
/**
* 建立不同許可權要求的InfoManager
*
* @param auth
* @return
*/
public static InfoManager getSelectivityAuthInstance(AuthProxy auth) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(InfoManager. class );
enhancer.setCallbacks( new Callback[] { auth, NoOp.INSTANCE });
enhancer.setCallbackFilter( new AuthProxyFilter());
return (InfoManager) enhancer.create();
}
} 記住:setCallbacks中的攔截器(interceptor)的順序,一定要和 CallbackFilter裡面指定的順序一致。。切忌。
Client.java public class Client {
public static void main(String[] args) {
Client c = new Client();
c.selectivityAuthManager();
}
/**
* 類比:沒有許可權的會員,可以作查詢操作
*/
public void selectivityAuthManager() {
System.out.println( " the loginer's name is not maurice,so have no permits do manager except do query operator " );
InfoManager authManager = InfoManagerFactory.getSelectivityAuthInstance( new AuthProxy( " maurice1 " ));
doCRUD(authManager);
separatorLine();
}