一、代理概述
代理是一种Java常用的设计模式,实现代理需要委托类和代理类都有相同的方法。代理提供了对委托类的访问方法,代理类不进行具体的业务逻辑操作,而是调用委托类的相同方法来进行逻辑处理,代理类一般在委托类实现的基础上还能进行一些别的操作。
- JAVA代理的方法一般分为静态代理和动态代理。
二、静态代理
静态代理指代理类在运行前已经知道代理类和委托类的关系。
直接用生活中的例子来看:我需要买一台电脑,我没用能力直接从厂商那里购买,只能通过京东淘宝等平台来购买,这里我就是一个用户,京东淘宝平台上的上架就是代理,电脑厂家就是目标对象。
1、定义业务
定义一个卖电脑的接口
package Proxy;
public interface ComputerSale {
float sellComputer();
}
2、定义实现接口的实现类
有厂商生产了电脑要卖出去
package Proxy;
public class HpComputer implements ComputerSale{
@Override
public float sellComputer() {
return 5000.0f;
}
}
3、定义代理
代理从厂商拿货卖出去,这里直接以TaoBao为例
package Proxy;
public class TaoBao implements ComputerSale{
private ComputerSale factory = new ComputerFactory();
@Override
public float sellComputer() {
float price = factory.sellComputer();
return price + 1500;
}
}
这两家都是代理销售电脑的代理类
4、定义消费者类来购买电脑
消费者可以通过TaoBao来购买电脑
package Proxy;
public class ProxyTest {
public static void main(String[] args) {
TaoBao taoBao = new TaoBao();
float price2 = taoBao.sellComputer();
System.out.println("taobao's price is: " + price2);
}
}
5、运行结果
以下是运行结果
6、优缺点
通过上述的代码可以看出静态代理实现很简单,其实和组合继承之类的差不多也利于理解,但是实际使用中我们可能并不知道委托和代理的具体关系,并且如果接口增加了方法,那么除了目标类要实现这个方法,每个代理类都得相应的实现该方法,增加了维护的难度。
三、动态代理
为了解决静态代理必须实现接口所有方法的问题,我们可以用动态代理来实现,有两种方法
1、JDK动态代理
JDK的动态代理只能代理接口
实现步骤
通过实现 InvocationHandler 接口创建自己的调用处理器
通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类
通过反射机制获得动态代理类的构造函数(jdk自带,不需手动处理)
通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入(jdk自带,不需手动处理)
创建调用处理器
package Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class SellHandle implements InvocationHandler {
private Object target = null;
public SellHandle(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 目标对象
Object result = null;
result = method.invoke(target,args);
// 功能增强 简化一下 统一加价
if (null != result){
float price = (float)result;
price += 1000;
result = price;
}
return result;
}
}
模拟购买
package Proxy;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
// 创建厂商对象
ComputerFactory computerFactory = new ComputerFactory();
// 创建代理处理对象
SellHandle sellHandle = new SellHandle(computerFactory);
// 获取目标类的类加载器,实现接口等信息
Class clazz = computerFactory.getClass();
ClassLoader classLoader = clazz.getClassLoader();
Class<?>[] InterFace = clazz.getInterfaces();
// 创建代理对象
ComputerSale computerSale = (ComputerSale) Proxy.newProxyInstance(classLoader,InterFace,sellHandle);
//通过代理对象执行方法
float price = computerSale.sellComputer();
System.out.println(price);
}
}
原理
生成一个代理类,这个代理类继承Proxy类并且实现了我们定义的接口,代理对象调用方法的时候,调用这个代理对象的一个成员InvocationHandler(上面我们传入了一个InvocationHandler实现对象)的方法,也就是我们包装了委托类后的方法。
2、cglib实现动态代理
暂时咕咕咕