JAVA代理方式使用示例總結


JAVA代理方式使用示例總結

一、    代理方式概括

  Java的代理方式主要包含了靜態代理,動態代理兩種方式,其中,動態代理根據實現的方式不同,又可以划分為jdk動態代理和cglib動態代理.

二、    代理方式實現

1.    靜態代理

  靜態代理,主要包含兩個實例,被代理類和代理類,兩者都要實現公共的接口,能夠面向接口實現,把被代理類組合到代理類中,在被代理類的本身功能上,加上代理類的自己的處理邏輯,達到增強的效果,就簡單的實現了代理功能.靜態代理只能事先編寫好代理代碼,經過統一編譯后才能執行.下面簡單的代碼實現:

1.1建立公共的接口

package jdkcglib.dynmicagent;

/**
 * 〈一句話功能簡述〉<br>
 * 〈功能詳細描述〉
 *
 * @author 12061799
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public interface IBookFacade {

    /**
     * 
     * 功能描述: <br>
     * 〈功能詳細描述〉
     *
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */
    void addBook(String name);

    /**
     * 
     * 功能描述: <br>
     * 〈功能詳細描述〉
     *
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */
    void deleteBook();

}

1.2建立被代理類

 
        
package jdkcglib.dynmicagent;

/**
 * 〈一句話功能簡述〉<br>
 * 〈功能詳細描述〉
 *
 * @author 12061799
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class BookFacade implements IBookFacade {

    @Override
    public void addBook(String name) {
        System.out.println("增加圖書!"+name);
    }

    @Override
    public void deleteBook() {
        System.out.println("刪除圖書!");
    }
}

1.3建立代理類

package com.lilin.maven.service;

/**
 * @author lilin
 * 
 */
public class BookFacadeProxy implements IBookFacade {
    private BookFacade bookFacade;

    public BookFacadeProxy(BookFacade bookFacade) {
        this.bookFacade = bookFacade;
    }

    @Override
    public void addBook(String name) {
        System.out.println("新增之前。。。");
        bookFacade.addBook("紅樓夢");
        System.out.println("新增之后。。。");
    }

    @Override
    public void deleteBook() {
        System.out.println("刪除之前。。。");
        bookFacade.deleteBook();
        System.out.println("刪除之后。。。");
    }

}

 

1.4建立測試類

package jdkcglib.dynmicagent;

/**
 * 〈一句話功能簡述〉<br>
 * 〈功能詳細描述〉
 *
 * @author 12061799
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class Test {

    /**
     * 功能描述: <br>
     * 〈功能詳細描述〉
     *
     * @param args
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */

    public static void main(String[] args) {
      BookFacadeProxy proxy = new BookFacadeProxy(new BookFacade());
      proxy.addBook("紅樓夢");
      proxy.deleteBook();
    }

}

2.    動態代理---jdk動態代理(InvocationHandler 接口)

  依據java的反射機制動態生成.在運行期間可以動態生成被代理類的實例.利用反射。獲取托付類的類載入器。托付類的全部接口,實例化代理類。通過反射類Proxy以及InvationHandler回調接口實現的。可是動態代理類僅僅能對該類所實現的接口中的方法進行代理。具有一定的局限性,而且反射的效率也不是非常高。下面是簡單的代碼實現:

2.1 建立公共接口類

package jdkcglib.dynmicagent;

/**
 * 〈一句話功能簡述〉<br>
 * 〈功能詳細描述〉
 *
 * @author 12061799
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public interface IBookFacade {

    /**
     * 
     * 功能描述: <br>
     * 〈功能詳細描述〉
     *
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */
    void addBook(String name);

    /**
     * 
     * 功能描述: <br>
     * 〈功能詳細描述〉
     *
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */
    void deleteBook();

}

2.2 建立被代理類

package jdkcglib.dynmicagent;

/**
 * 〈一句話功能簡述〉<br>
 * 〈功能詳細描述〉
 *
 * @author 12061799
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class BookFacade implements IBookFacade {

    @Override
    public void addBook(String name) {
        System.out.println("新增加圖書!"+name);
    }

    @Override
    public void deleteBook() {
        System.out.println("直接刪除圖書!");
    }

}

2.3 建立代理類

package jdkcglib.dynmicagent;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 〈一句話功能簡述〉<br>
 * 〈功能詳細描述〉
 * 
 * @author 12061799
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class BookFacadeProxy implements InvocationHandler {

    /**
     * 被代理對象
     */
    private Object target;

    /**
     * 
     * 功能描述: <br>
     * 〈功能詳細描述〉綁定被代理對象 返回代理對象
     * 
     * @param target
     * @return
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */
    public Object bind(Object target) {
        this.target = target;
        // 要綁定接口(這是一個缺陷,cglib彌補了這一缺陷)
        // 返回代理對象
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        if (method.getName().startsWith("delete")) {
            System.out.println("#####方法執行之前#####");
            result = method.invoke(target, args);
            System.out.println("#####方法執行之后#####");
        } else {
            result = method.invoke(target, args);
        }
        return result;
    }

}

2.4 建立測試類

package jdkcglib.dynmicagent;

/**
 * 〈一句話功能簡述〉<br>
 * 〈功能詳細描述〉
 *
 * @author 12061799
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class Test {

    /**
     * 功能描述: <br>
     * 〈功能詳細描述〉
     *
     * @param args
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */
    public static void main(String[] args) {
        BookFacadeProxy proxy = new BookFacadeProxy();
        IBookFacade bookProxy = (IBookFacade) proxy.bind(new BookFacade());
        bookProxy.addBook("紅樓夢");
        bookProxy.deleteBook();
    }
}

3.    動態代理---CGLIB動態代理(MethodInterceptor 接口)

  CGLib (Code Generation Library) 是一個強大的,高性能,高質量的Code生成類庫。它能夠在執行期擴展Java類與實現Java接口。不僅僅能夠接管接口類的方法,同時還能夠接管普通類的方法.解決了jdk代理的只能代理接口類方法的難處,CGLib 的底層是Java字節碼操作框架(ASM).動態的生成被代理類的子類, 增強的代碼是硬編碼在新生成的類文件內部的,不會存在反射的性能問題.下面是簡單的代碼實現:

3.1 建立被代理類

package jdkcglib.cglib;

/**
 * 〈一句話功能簡述〉<br>
 * 〈功能詳細描述〉
 *
 * @author 12061799
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class BookFacade {

    public void addBook() {
        System.out.println("增加圖書的普通方法...");
    }

}

3.2 建立代理類

package jdkcglib.cglib;

import java.lang.reflect.Method;

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

/**
 * 〈一句話功能簡述〉<br>
 * 〈功能詳細描述〉
 *
 * @author 12061799
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class BookFacadeCglib implements MethodInterceptor {

    private Object target;

    /**
     * 創建代理對象
     * 
     * @param target
     * @return
     */
    public Object getInstance(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        // 回調方法
        enhancer.setCallback(this);
        // 創建代理對象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("方法執行之前");
        proxy.invokeSuper(obj, args);
        System.out.println("方法執行之后");
        return null;
    }

}

3.3  建立測試類

package jdkcglib.cglib;

import java.io.UnsupportedEncodingException;

/**
 * 
 * 〈一句話功能簡述〉<br>
 * 〈功能詳細描述〉
 * 
 * @author 12061799
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class TestCglib {
    /**
     * 
     * 功能描述: <br>
     * 〈功能詳細描述〉
     * 
     * @param args
     * @throws UnsupportedEncodingException
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */
    public static void main(String[] args) throws UnsupportedEncodingException {
        BookFacadeCglib cglib = new BookFacadeCglib();
        BookFacade bookCglib = (BookFacade) cglib.getInstance(new BookFacade());
        bookCglib.addBook();
    }

}

三、  java代理小結

靜態代理: 代理類就是通過調用被代理類的方法進行執行的,自己本身並不用清楚被代理類的方法.需要編譯后執行.耦合比較緊密.

JDK動態代理: 利用反射原理,動態的生成代理類,將類的載入延遲到程序執行之中,解耦了代理類和被代理類的聯系.主要要實現InvationHandler接口.

CGLIB動態代理:原理是繼承,把被代理類作為父類,動態生成被代理類的子類,三個步驟,設置父類,設置回調函數,創建子類.實現MethodInterceptor 接口,攔截調用父類方法時,會處理回調方法,處理自己的增強方法.

參考:

http://www.cnblogs.com/bhlsheji/p/5316693.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM