CGlib動態代理-簡單介紹
CGlib簡單介紹
CGlib概述:
cglib(Code Generation Library)是一個強大的,高效能,高質量的Code生成類庫。它可以在執行期擴充套件Java類與實現Java介面。
cglib封裝了asm,可以在執行期動態生成新的class。
cglib用於AOP,jdk中的proxy必須基於介面,cglib卻沒有這個限制。
CGlib應用:
以一個例項在簡單介紹下cglib的應用。
我們模擬一個虛擬的場景,關於資訊的管理。
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();
}
/**
* 對Info做增加/更新/刪除/查詢操作
*
* @param manager
*/
private void doCRUD(InfoManager manager) {
manager.create();
manager.update();
manager.delete();
manager.query();
}
/**
* 加一個分隔行,用於區分
*/
private void separatorLine() {
System.out.println("################################");
}
}
至此,沒有涉及到cglib的內容,因為需求太簡單了,但是接下來,需求發生了改變,要求:
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();
}
/**
* 對Info做增加/更新/刪除/查詢操作
*
* @param manager
*/
private void doCRUD(InfoManager manager) {
manager.create();
manager.update();
manager.delete();
manager.query();
}
/**
* 加一個分隔行,用於區分
*/
private void separatorLine() {
System.out.println("################################");
}
}
執行下程式碼,發現這時client端中已經加上了許可權校驗。
同樣是InfoManager,為什麼這時能多了許可權的判斷呢?Factory中enhancer.create()返回的到底是什麼物件呢?這個疑問將在第三部分CGlib中解釋。
這邊的程式碼,其實是介紹了cglib中的enhancer功能.
到這裡,參照上面的程式碼,就可以使用cglib帶來的aop功能了。但是為了更多介紹下cglib的功能,模擬需求再次發生變化:
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;
/**
* <pre>
* 選擇使用的proxy
* 如果呼叫query函式,則使用第二個proxy
* 否則,使用第一個proxy
* </pre>
*/
@Override
public int accept(Method method) {
if ("query".equals(method.getName())) {
return AUTH_NOT_NEED;
}
return AUTH_NEED;
}
}
這段程式碼什麼意思?其中的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();
}
/**
* 對Info做增加/更新/刪除/查詢操作
*
* @param manager
*/
private void doCRUD(InfoManager manager) {
manager.create();
manager.update();
manager.delete();
manager.query();
}
/**
* 加一個分隔行,用於區分
*/
private void separatorLine() {
System.out.println("################################");
}
}
此時,對於query的許可權校驗已經被去掉了。
通過一個模擬需求,簡單介紹了cglib aop功能的使用。
CGlib應用非常廣,在spring,hibernate等框架中,被大量的使用。
CGlib原理:
cglib神奇嗎?其實一旦瞭解cglib enhancer的原理,一切就真相大白了。
剛才在第二部分中,有個疑問:enhancer.create()到底返回了什麼物件?
其實在剛才的例子中,cglib在程式碼執行期,動態生成了InfoManager的子類,並且根據CallbackFilter的accept方法,覆寫了InfoManager中的所有方法--去執行相應的MethodInterceptor的intercept方法。
CGlib概述:
cglib(Code Generation Library)是一個強大的,高效能,高質量的Code生成類庫。它可以在執行期擴充套件Java類與實現Java介面。
cglib封裝了asm,可以在執行期動態生成新的class。
cglib用於AOP,jdk中的proxy必須基於介面,cglib卻沒有這個限制。
CGlib應用:
以一個例項在簡單介紹下cglib的應用。
我們模擬一個虛擬的場景,關於資訊的管理。
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();
}
/**
* 對Info做增加/更新/刪除/查詢操作
*
* @param manager
*/
private void doCRUD(InfoManager manager) {
manager.create();
manager.update();
manager.delete();
manager.query();
}
/**
* 加一個分隔行,用於區分
*/
private void separatorLine() {
System.out.println("################################");
}
}
至此,沒有涉及到cglib的內容,因為需求太簡單了,但是接下來,需求發生了改變,要求:
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();
}
/**
* 對Info做增加/更新/刪除/查詢操作
*
* @param manager
*/
private void doCRUD(InfoManager manager) {
manager.create();
manager.update();
manager.delete();
manager.query();
}
/**
* 加一個分隔行,用於區分
*/
private void separatorLine() {
System.out.println("################################");
}
}
執行下程式碼,發現這時client端中已經加上了許可權校驗。
同樣是InfoManager,為什麼這時能多了許可權的判斷呢?Factory中enhancer.create()返回的到底是什麼物件呢?這個疑問將在第三部分CGlib中解釋。
這邊的程式碼,其實是介紹了cglib中的enhancer功能.
到這裡,參照上面的程式碼,就可以使用cglib帶來的aop功能了。但是為了更多介紹下cglib的功能,模擬需求再次發生變化:
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;
/**
* <pre>
* 選擇使用的proxy
* 如果呼叫query函式,則使用第二個proxy
* 否則,使用第一個proxy
* </pre>
*/
@Override
public int accept(Method method) {
if ("query".equals(method.getName())) {
return AUTH_NOT_NEED;
}
return AUTH_NEED;
}
}
這段程式碼什麼意思?其中的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();
}
/**
* 對Info做增加/更新/刪除/查詢操作
*
* @param manager
*/
private void doCRUD(InfoManager manager) {
manager.create();
manager.update();
manager.delete();
manager.query();
}
/**
* 加一個分隔行,用於區分
*/
private void separatorLine() {
System.out.println("################################");
}
}
此時,對於query的許可權校驗已經被去掉了。
通過一個模擬需求,簡單介紹了cglib aop功能的使用。
CGlib應用非常廣,在spring,hibernate等框架中,被大量的使用。
CGlib原理:
cglib神奇嗎?其實一旦瞭解cglib enhancer的原理,一切就真相大白了。
剛才在第二部分中,有個疑問:enhancer.create()到底返回了什麼物件?
其實在剛才的例子中,cglib在程式碼執行期,動態生成了InfoManager的子類,並且根據CallbackFilter的accept方法,覆寫了InfoManager中的所有方法--去執行相應的MethodInterceptor的intercept方法。
相關文章
- CGLib 動態代理CGLib
- 動態代理-cglib分析CGLib
- JDK動態代理和 CGLIB 代理JDKCGLib
- JDK動態代理和CGLib代理JDKCGLib
- Java代理(jdk靜態代理、動態代理和cglib動態代理)JavaJDKCGLib
- 3.靜態代理&動態代理&CGlibCGLib
- 代理模式詳解:靜態代理、JDK動態代理與Cglib動態代理模式JDKCGLib
- spring aop原理 JDK動態代理和CGLIB動態代理SpringJDKCGLib
- 靜態代理和動態代理(jdk/cglib)詳解JDKCGLib
- Java動態代理(JDK和cglib)JavaJDKCGLib
- 你必須會的 JDK 動態代理和 CGLIB 動態代理JDKCGLib
- 簡單介紹靜態路由路由
- 設計模式之cglib動態代理設計模式CGLib
- 【深度思考】聊聊CGLIB動態代理原理CGLib
- CGLib動態代理原理及實現CGLib
- 簡單介紹nginx反向代理及使用Nginx
- 淺析動態代理IP 海外代理IP介紹
- cglib動態代理和jdk動態代理的區別與應用CGLibJDK
- 動態代理竟然如此簡單!
- java 動態代理簡單使用Java
- 動態代理jdk和cglib的區別JDKCGLib
- Spring動態代理的生成-如何判斷是使用JDK動態代理還是CGlib代理SpringJDKCGLib
- 模擬簡單的動態代理
- 由《尋秦記》說代理模式(靜態,動態,CGLib)模式CGLib
- 動態代理jdk的Proxy與spring的CGlibJDKSpringCGLib
- 基於 CGLIB 庫的動態代理機制CGLib
- SSM-Spring-10:Spring中cglib動態代理SSMSpringCGLib
- Java JDK Proxy和CGLib動態代理示例講解JavaJDKCGLib
- JDK 和 CGLib 實現動態代理和區別JDKCGLib
- SpringAOP中JDK和CGLib動態代理哪個更快?SpringJDKCGLib
- 設計模式【3.3】-- CGLIB動態代理原始碼解讀設計模式CGLib原始碼
- Jmh測試JDK,CGLIB,JAVASSIST動態代理方式的效能JDKCGLibJava
- Java動態代理 jdk和cglib的實現比較JavaJDKCGLib
- Map簡單介紹
- SVG簡單介紹SVG
- Clickjacking簡單介紹
- 【Pandas】簡單介紹
- ActiveMQ簡單介紹MQ
- JSON簡單介紹JSON