三种代理模式

2021/11/1 23:41:03

本文主要是介绍三种代理模式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

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代理:不需要目标类 实现接口


这篇关于三种代理模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程