三種代理模式


1 概念

代理:proxy  結構性模式中的代理模式
     要調用目標對象的功能時:不是直接訪問目標對象  而是通過代理對象 間接訪問目標對象的功能:
     對目標對象的功能進行擴展
代理對象:對目標對象的功能進行改進和加功
目標對象:功能被擴展的對象

2 靜態代理

要求:

靜態代理:為目標對象創建一個代理類:代理類需要關聯目標對象 代理類和目標對象實現相同的接口/繼承相同的父類
        在代理類方法中調用目標對象的方法  在調用之前和之后可以加擴展的代碼
目標對象和代理類 必須實現相同的接口或者相同的父類

准備

  • 接口
public interface WorkerInterface {

	void work();

	void smoke(String smokeLogo);

	void sleep();

}
  • 目標對象的類
public class Worker implements WorkerInterface {
	private String wname;

	public Worker(String wname) {
		this.wname = wname;
	}
	public void work(){
		System.out.println("工人:"+wname+",開始工作了!");
	}
	public void smoke(String smokeLogo){
		System.out.println("工人:"+wname+",正在吸煙,煙的牌子是"+smokeLogo+"!");
	}
	public void sleep(){
		System.out.println("工人:"+wname+",正在休息!");
	}

	@Override
	public String toString() {
		return "Worker [wname=" + wname + "]";
	}
	
}
  • 代理對象的類
package proxy;

public class Proxy {

	public static void main(String[] args) {
		// 4 創建目標對象
		Worker worker = new Worker("張三");
		// 5 創建代理對象 並關聯目標
		WorkerProxy wp = new WorkerProxy(worker);
		// 6 調用代理對象的方法
		wp.sleep();
		wp.work();
		wp.smoke("中華");
	}

}

// 1 實現相同接口
class WorkerProxy implements WorkerInterface {
	// 2 關聯目標對象
	private WorkerInterface worker;

	public WorkerProxy(WorkerInterface worker) {
		this.worker = worker;
	}
	// 3 在代理對象的方法中 調用目標對象的方法 在調用之前和之后可以加擴展的代碼

	@Override
	public void work() {
		worker.work();
		System.out.println(worker + "辛苦了!");
		System.out.println("*************************************");

	}

	@Override
	public void smoke(String smokeLogo) {
		System.out.println(worker + "吸煙有害健康!");
		worker.smoke(smokeLogo);
		System.out.println("*************************************");
	}

	@Override
	public void sleep() {
		System.out.println(worker + "勞逸結合!");
		worker.sleep();
		System.out.println(worker + "睡覺結束,滿血復活!");
		System.out.println("*************************************");
	}

}

總結

優點:可以實現對目標對象功能的擴展
缺點:1 只能代理指定接口的實現類
     2 不能對目標對象的特有功能進行擴展

3 動態代理(jdk代理)

概念

*動態代理:
*  1.不需要聲明定義一個代理類
*  2.代理對象的生成,是利用JDK的API,動態的在內存中構建代理對象(需要我們指定創建代理對象/目標對象實現的接口的類型)
*  3.動態代理也叫做:JDK代理
*  
*通過java.lang.reflect. Proxy 的newProxyInstance方法在內存中動態生成目標對象的代理對象
*** 動物類 ***

package proxy;

public class Cat implements Animal{
    public void eat(){
        System.out.println("貓愛吃魚!");
    }
}
interface  Animal{
    void eat();
}

代理對象的工廠類:寫法1:普通寫法

package proxy;

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

public class ProxyF {

	public static void main(String[] args) {
		// 創建目標對象
		Worker w = new Worker("林風");
		// 創建工廠對象
		ProxyFactory factroy = new ProxyFactory(w);
		// 通過工廠對象動態獲取一個代理對象
		WorkerInterface wi = (WorkerInterface) factroy.getProxy();
		wi.sleep();
		wi.work();
		wi.smoke("芙蓉王");
		
	    //創建工廠對象
	    ProxyFactory factroy2=new ProxyFactory(new Cat()); 
	    Animal a=(Animal)factroy2.getProxy();
	    a.eat();

	}

}

// 1 定義一個代理類工廠對象:實現接口InvocationHandler
class ProxyFactory implements InvocationHandler {
	// 2 定義引用記錄目標對象:通過構造方法關聯
	private Object target;

	public ProxyFactory(Object target) {
		this.target = target;
	}

	// 3 定義方法: 通過Proxy的newProxyInstance方法動態的在內存中創建目標對象的代理對象
	public Object getProxy() {
		/**
		 * newProxyInstance三個參數 
		 * 1 loader: 用哪個類加載器去加載代理對象 
		 * 2 interfaces:動態代理類需要實現的接口 
		 * 3 h:動態代理方法在執行時,會調用h里面的invoke方法去執行
		 **/
		return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}

	// 4 實現InvocationHandler的invoke方法:目標對象的每個方法被調用:此invoke方法發都會被調用一次
	/**
	 * invoke三個參數 
	 * 1 proxy:就是代理對象,newProxyInstance方法的返回對象 
	 * 2 method:調用的方法 
	 * 3 args:方法中的參數
	 **/
	@Override
	public Object invoke(Object obj, Method method, Object[] params) throws Throwable {
		System.out.println(method + ":" + params + ":::方法執行前的擴展");
		Object result = null;
		result = method.invoke(target, params);
		System.out.println(method + ":" + params + ":::方法執行后的擴展");
		System.out.println("*******************************************");
		return result;
	}
}

代理對象的工廠類:寫法2:匿名內部類來實現

package proxy;

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

public class ProxyF {

	public static void main(String[] args) {
		// 創建目標對象
		Worker w = new Worker("林風");
		// 創建工廠對象
		ProxyFactory factroy = new ProxyFactory(w);
		// 通過工廠對象動態獲取一個代理對象
		WorkerInterface wi = (WorkerInterface) factroy.getProxy();
		wi.sleep();
		wi.work();
		wi.smoke("芙蓉王");

		// 創建工廠對象
		ProxyFactory factroy2 = new ProxyFactory(new Cat());
		Animal a = (Animal) factroy2.getProxy();
		a.eat();

	}

}

class ProxyFactory {
	// 定義引用記錄目標對象:通過構造方法關聯
	private Object target;

	public ProxyFactory(Object target) {
		this.target = target;
	}

	// 定義方法: 通過Proxy的newProxyInstance方法動態的在內存中創建目標對象的代理對象
	public Object getProxy() {
		/**
		 * newProxyInstance三個參數 
		 * 1 loader: 用哪個類加載器去加載代理對象
		 * 2 interfaces:動態代理類需要實現的接口 
		 * 3 h:動態代理方法在執行時,會調用h里面的invoke方法去執行
		 **/
		return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),
				new InvocationHandler() {
					/**
					 * invoke三個參數 
					 * 1 proxy:就是代理對象,newProxyInstance方法的返回對象 
					 * 2 method:調用的方法 
					 * 3 args:方法中的參數
					 **/
					// 實現InvocationHandler的invoke方法:目標對象的每個方法被調用:此invoke方法發都會被調用一次
					@Override
					public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
						System.out.println(method + ":" + params + ":::方法執行前的擴展");
						Object result = null;
						result = method.invoke(target, params);
						System.out.println(method + ":" + params + ":::方法執行后的擴展");
						System.out.println("************************************************************");
						return result;
					}

				});
	}
}

總結

jdk代理:可以代理任意目標對象:但目標類必須實現接口

4 cglib代理

概念

     * CGLIB代理:子類對象
     *    在運行時期,在內存中動態的創建一個目標對象類的子類對象
     *    被spring框架的aop使用:依賴的jar被融入到了spring-core的jar
     * 先導入jar:   spring-core-3.2.18.RELEASE.jar
     * 優點:可以為所有對象動態創建代理對象::不需要目標對象實現接口   

目標對象類

class Book{
	public int add(int a,int b){
		System.out.println(a+"+"+b+"="+(a+b));
		return a+b;
	}
}

代理工廠類

package proxy;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class ProxyF {

	public static void main(String[] args) {
		// 創建目標對象
		Book b = new Book();
		// 創建工廠對象
		ProxyFactory factroy = new ProxyFactory(b);
		// 通過工廠對象動態獲取一個代理對象
		Book bproxy = (Book) factroy.getProxy();
		// 調用代理對象的方法;
		System.out.println(bproxy.add(1, 2));
	}
}

// 1 創建代理工廠類 實現接口MethedInterceptor
class ProxyFactory implements MethodInterceptor {
	// 2 關聯目標對象
	private Object target;

	public ProxyFactory(Object target) {
		this.target = target;
	}

	// 3 創建方法獲取代理對象
	public Object getProxy() {
		// 1 創建工具類
		Enhancer eh = new Enhancer();
		// 2 指定父類
		eh.setSuperclass(target.getClass());
		// 3 設置回調函數
		eh.setCallback(this);
		// 4 獲取代理對象
		return eh.create();
	}

	/**
	 * intercept四個參數 
	 * 1 Object o:代理對象本身 
	 * 2 Method method: 被代理對象的方法 
	 * 3 Object[] objects:函數調用的參數 
	 * 4 MethodProxy methodProxy:方法的代理
	 **/
	// 4 實現intercep方法:目標對象的方法每次被調用 此方法都會被調用
	@Override
	public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
		System.out.println("cglib代理:::方法執行前的擴展代碼");
		Object result = null;
		result = arg1.invoke(target, arg2);
		System.out.println("cglib代理:::方法執行后的擴展代碼");
		return result;
	}
}

總結

cglib代理:不需要目標類 實現接口


免責聲明!

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



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