proxyNote - juedaiyuer/researchNote GitHub Wiki

#代理模式#

为其他对象提供一种代理以控制对这个对象的访问
代理对象起中介作用,可去掉功能服务或增加额外的服务

对象消耗太多资源,并不是每一条逻辑路径都需要这个对象,延迟创建对象的想法
限制访问某个对象,提供一组方法给普通用户,特殊方法给管理员用户

远程代理

Remote Proxy
为不同地理的对象,提供局域网代表对象 远程代理又称之为大师(Ambassador)

远程代理

虚拟代理

virtual Proxy
根据需要将资源消耗很大的对象进行延迟真正需要的时候进行创建

保护代理

权限控制

智能引用代理

提供额外的服务 取代简单的指针,它在访问对象时执行一些附加操作

Copy-on-Write代理

虚拟代理的一种,把复制(克隆)操作延迟到只有客户端真正需要时才执行

两种实现方式

  1. 静态代理
  2. 动态代理

静态代理

代理和被代理对象在代理之前是确定的,他们实现相同的接口或者继承相同的抽象类

汽车行驶

package proxyDemo;

public interface Moveable {
	void move();
}


package proxyDemo;

import java.util.Random;

public class Car implements Moveable {
	
	@Override
	public void move() {
		long startTime = System.currentTimeMillis();
		System.out.println("汽车开始行驶");
		try {
			System.out.println("汽车行驶中");
			Thread.sleep(new Random().nextInt(1000)); //随即产生一个大于0小于1000的整数;用进程的例子模拟汽车行驶
			
		} catch (InterruptedException e) {		
			e.printStackTrace();
		}

		long endTime = System.currentTimeMillis();
		System.out.println("汽车结束行驶");
		System.out.println("汽车行驶时间:"+(endTime-startTime)+"ms");
	}

}

使用代理方式

import java.util.Random;

public class Car implements Moveable {
	
	@Override
	public void move() {

		try {
			System.out.println("汽车行驶中");
			Thread.sleep(new Random().nextInt(10000));
		
		} catch (InterruptedException e) {		
			e.printStackTrace();
		}

	}

}

package proxyDemo;

public class proxyCar extends Car {

	@Override
	public void move() {
		long startTime = System.currentTimeMillis();
		System.out.println("汽车开始行驶");
		super.move();
		long endTime = System.currentTimeMillis();
		System.out.println("汽车结束行驶");
		System.out.println("汽车行驶时间:"+(endTime-startTime)+"ms");
	}

}

二者的测试类

package proxyDemo;

public class Test {

	public static void main(String[] args) {
//		Car benz = new Car();
//		benz.move();

		Moveable m = new proxyCar();
		m.move();
	
	}

}

代理简单结构示意图

代理UML

  1. 抽象对象 声明了目标对象和代理对象的共同接口
  2. 目标对象 定义了代理对象所代表的目标对象
  3. 代理对象 内部含有目标对象的引用,从而在任何时候操纵目标对象,代理对象提供了与目标对象相同的接口,在任何时候可以替代目标对象.

##JDK动态代理##

jdk动态代理

java动态代理类位于java.lang.reflect包下,一般主要涉及两个类:

1.Interface InvocationHandler

public object invoke(Object obj,Method method,Object[] args)

这个抽象方法在代理类中动态实现

2.Proxy

static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)

返回代理类的一个实例,返回后的代理类可以当作被代理类使用

代码如下

package jdkproxy;

public interface Moveable {
	void move();
}


package jdkproxy;

public class Car implements Moveable{
	public void move()
	{
		System.out.println("---汽车行驶中---");
	}

}

package jdkproxy;

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

public class TimeHandler implements InvocationHandler {

public TimeHandler(Object target) {
	super();
	this.target = target;
}

private Object target;

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	// TODO Auto-generated method stub

	System.out.println("---时间处理---");

	method.invoke(target);

	System.out.println("---时间结束---");
	return null;
}

}

package jdkproxy;

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



//JDK动态代理测试类

public class Test {

	public static void main(String[] args) {
	
		Car car = new Car();
		InvocationHandler h = new TimeHandler(car);
		Class<?> cls = car.getClass();
	
		Moveable m =(Moveable)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),h);
		m.move();

	}

}	

##cglib##

导入jar包,cglib-nodep-().jar

JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢?
CGLIB是直接继承代理

性能:CGLib>JDK
时间耗费:JDK时间效率高
单例的对象使用CGLib


代码示例

public class SayHello {
 public void say(){
  System.out.println("hello everyone");
 }
} 


public class CglibProxy implements MethodInterceptor{
 private Enhancer enhancer = new Enhancer();
 public Object getProxy(Class clazz){
  //设置需要创建子类的类
  enhancer.setSuperclass(clazz);
  enhancer.setCallback(this);
  //通过字节码技术动态创建子类实例
  return enhancer.create();
 }
 //实现MethodInterceptor接口方法
 public Object intercept(Object obj, Method method, Object[] args,
   MethodProxy proxy) throws Throwable {
  System.out.println("前置代理");
  //通过代理类调用父类中的方法
  Object result = proxy.invokeSuper(obj, args);
  System.out.println("后置代理");
  return result;
 }
}


public class DoCGLib { 
 public static void main(String[] args) { 
  CglibProxy proxy = new CglibProxy(); 
  //通过生成子类的方式创建代理类 
  SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class); 
  proxyImp.say(); 
 } 
} 

##JDK动态代理的内部实现##

动态代理实现思路 实现功能:通过Proxy的newProxyInstance返回代理对象

  1. 声明一段源码(动态产生代理)
  2. 编译源码(JDK Compiler API),产生新的类(代理类)
  3. 将这个类load到内存当中,产生一个新的对象(代理对象)
  4. return 代理对象