使用cglib實現(xiàn)動態(tài)代理技術

Spring AOP(面向切面編程)使用了兩種技術實現(xiàn),一種是JDK自帶的動態(tài)代理,另外一種是使用cglib字節(jié)碼技術動態(tài)生成代理類。Spring是如何選擇的了:

  • 如果目標對象實現(xiàn)了接口,默認情況先回選擇使用JDK代理技術實現(xiàn)AOP,但是也可以強制使用cglib實現(xiàn)動態(tài)代理
  • 如果目標對象沒有實現(xiàn)接口,則會采用cglib技術實現(xiàn)AOP

cglib創(chuàng)建某個動態(tài)代理類的模式是:

  • 查找目標類上所有非 final 的public類型的方法,將這些方法的定義轉換成字節(jié)碼
  • 將組成的字節(jié)碼轉換成相應的代理的class對象
  • 代理類實現(xiàn)MethodInterceptor接口,用來處理代理類上所有方法的請求(中介)

下面是代碼:

定義一個通用接口,里面定義一些要攔截的方法

package com.minglangx.cglib;

/**
* 

  * @ClassName: UserService

  * @Description: 通用接口類

  * @author minglangx

  * @date 2017年8月19日 下午12:02:34

  *


  
*/
public interface UserService {

   String getName(String name);
   Integer getAge(int age);
   
}

定義一個目標對象,實現(xiàn)這個通用接口

package com.minglangx.cglib;
/**
 * 

  * @ClassName: UserServiceImpl

  * @Description: 目標對象

  * @author minglangx

  * @date 2017年8月19日 下午12:02:52

  *


  
 */
public class UserServiceImpl implements UserService {

    @Override
    public String getName(String name) {
        System.out.println("===getName===");
        return name;
    }

    @Override
    public Integer getAge(int age) {
        System.out.println("====getAge=====");
        return age;
    }

}

核心代理類,實現(xiàn)MethodInterceptor接口

package com.minglangx.cglib;

import java.lang.reflect.Method;
import java.util.Arrays;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 
 * 
 * @ClassName: CglibDemo
 * 
 * @Description: 代理類使用 Cglib實現(xiàn)動態(tài)代理
 * 
 * @author minglangx
 * 
 * @date 2017年8月18日 下午12:33:51
 *
 * 
 * 
 * 
 * 
 */
class CglibDemo implements MethodInterceptor {

    
    /**
     * Object obj 被代理的對象
     * Method method 被攔截的方法
     * Object[] objs 方法的參數(shù)
     * MethodProxy methodProxy  cglib中的代理對象
     * 
     * 
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] objs, MethodProxy methodProxy) throws Throwable {
        System.out.println("======before " + methodProxy.getSuperName() + "======");
        System.out.println("被攔截的方法名稱-----" + method.getName());
        System.out.println("被攔截的方法參數(shù)-----" + Arrays.asList(objs));
        //invokeSuper(obj,objs) 第一個參數(shù)是被代理對象,第二個參數(shù)是參數(shù)集合
        Object objNew = methodProxy.invokeSuper(obj, objs);
        System.out.println("+++++before " + methodProxy.getSuperName() + "=====");
        return objNew;
    }
    
    
    
    
    

}

測試類

  • 使用 Enhancer().setSuperclass(目標對象); 設置要代理的對象
  • 使用 Enchancer.setCallback(目標對象); 將要代理對象的所有方法都轉發(fā)到intercept()方法上進行攔截
  • 使用Enchancer.create();獲取被代理的對象
package com.minglangx.cglib;

import net.sf.cglib.proxy.Enhancer;
import com.minglangx.cglib.UserService;
import com.minglangx.cglib.UserServiceImpl;

public class MainDemo {

    public static void main(String[] args) {

        CglibDemo cglibDemo = new CglibDemo();
        //cglib中的加強器,用來創(chuàng)建動態(tài)代理
        Enhancer enhancer = new Enhancer();
               //設置要動態(tài)創(chuàng)建的類
        enhancer.setSuperclass(UserServiceImpl.class);
        /*
         * 設置回調(diào).這里相當于是對于代理類上所有方法的回調(diào),都會調(diào)用CallBack,
         * 而Callback需要執(zhí)行intercept()方法進行攔截
         */
        enhancer.setCallback(cglibDemo);
        
        //得到實際對象的接口類型,調(diào)用其方法
        UserService o =(UserService) enhancer.create();
        o.getName("zhangs");
        o.getAge(25);
        
        
        
        
    }

}

輸出結果: 我們看到在被代理對象調(diào)用方法之前成功實現(xiàn)了方法的攔截

image.png
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容