第六講 java動態代理與cglib動態代理


一、      理解動態代理設計模式

代理模式,是常用的Java設計模式,他的特徵是代理類與委託類有同樣的接口,代理類主要負責爲委託類預處理消息,過濾消息,把消息轉發給委託類,以及事後處理消息等。代理類與委託類之間通常會存在關聯關係,一個代理類的對象與一個委託類的對象關聯,代理類的對象本身並不真正實現業務,而是通過調用委託類的對象相關方法,來提供特定的服務。

動態代理類的字節碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。動態代理類不僅簡化了編程工作,而且提高了軟件系統的可擴展性,因爲Java反射機制可以生成任意類型的動態代理類。Java.lang.reflect包中的Proxy類和Invocationhandler接口提供了生成動態代理類的能力。

                   Java動態代理中包含一個類和一個接口:

                   InvocationHandler接口:

                   publicinterface InvocationHandler {

public Object invoke(Object proxy, Method method, Object[] args)

    throws Throwable;

                   參數說明:

                   Object proxy:指被代理的對象

        Method method:要調用的方法

        Object[] args:方法調用時需要的參數

        Proxy

        Proxy類是專門完成代理的操作類,可以通過此類爲一個或多個接口動態的生成一個實現類,此類提供瞭如下的操作方法:

       

  publicstatic Object newProxyInstance(ClassLoader loader,

                      Class<?>[] interfaces,

                      InvocationHandler h)

    throws IllegalArgumentException

    {

    if (h == null) {

        thrownew NullPointerException();

    }

 

                   參數說明:

                   ClassLoader loader:類加載器

        Class<?>[] interfaces:得到全部的接口

InvocationHandler h:得到InvocationHandler接口的子類實例

類加載器

    Proxy類中的newProxyInstance()方法中需要一個ClassLoader類的實例,ClassLoader實際上對應的是類加載器,在Java中主要有一下三種類加載器

    Bootstrap ClassLoader:此類加載器採用C++編寫,一般開發中看不到的;

    Extendsion ClassLoader:用來進行擴展類的加載,一般對應的是jre\lib\ext目錄中的類;

    AppClassLoader :(默認)加載classpath指定的類,是最常用的一種加載器

 

例子:

代理類:

package com.eden.proxy;

 

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

 

public class DAOProxy implements InvocationHandler {

//      委託類,及原代理類

         private Object originalObject;

        

         public Object bind(Object obj){

                   this.originalObject=obj;

                   return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);

         }

        

         private void preMothed(){

                   System.out.println("方法執行之前……");

         }

         private void afterMothed(){

                   System.out.println("方法執行之後……");

         }

         @Override

         public Object invoke(Object arg0, Method arg1, Object[] arg2)

                            throws Throwable {

                   this.preMothed();

                   Object result=arg1.invoke(this.originalObject, arg2);

                   System.out.println(" arg0  classname="+arg0.getClass().getName());

                   this.afterMothed();

                   return result;

         }

 

}

 測試類:

import com.eden.dao.StudentsDAO;

import com.eden.dao.impl.StudentsImpl;

import com.eden.proxy.DAOProxy;

 

import junit.framework.TestCase;

 

 

publicclass TestProxy extends TestCase {

    publicvoid testProxy(){

        StudentsDAO sdao= new StudentsImpl();

        DAOProxy proxy=new DAOProxy();

        sdao=(StudentsDAO) proxy.bind(sdao);

        sdao.savaStudents();

    }

   

}

 

 

 

二、      Cglib動態代理

Jdk的動態代理依靠接口實現,如果有些類並沒有實現接口,則不能使用jdk代理,這就要使用cglib動態代理了。

Cglib是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,並覆蓋其中的方法實現增強,但因爲採用的是繼承,所以不能對final修飾的類進行代理。

Bytecodejava 的二進制字節碼文件。

ASM:爲Java字節碼文件進行反彙編的工具

CGLIB GroovyBeanShell :爲三個常用動態代理組件

Hibernate Spring AOP Dynaop,etc 使用CGLIB的常見框架

Applications :應用

MethedInterceptor接口

         接口方法

         Public Object    Intercept(Object obj,Method method,Object[] args MethodProxy proxy) throw Throwable

         參數介紹:

         Obj:代理對象

         Method:攔截的方法

         Args:方法參數

         Proxy:攔截器

 

三、      Spring

兩種代理模式都支持,Spring默認使用的是jdk proxy

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章