本文主要先讲解代理模式的概念,对代理设计模式 、动态代理设计模式描述与代码演示。
目录
1. 什么是代理设计模式
代理模式是Java常见的设计模式之一。所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象。
2. 为什么会用代理设计模式
为什么要采用这种间接的形式来调用对象呢?一般是因为客户端不想直接访问实际的对象,或者访问实际的对象存在困难,因此通过一个代理对象来完成间接的访问。
3. 适用场景
在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用代理模式。下面是一些可以使用代理模式常见情况:
1)远程代理(Remote Proxy)为一个对象在不同的地址空间提供局部代表。
2)虚代理(Virtual Proxy)根据需要创建开销很大的对象。
3)保护代理(Protection Proxy)控制对原始对象的访问。保护代理用于对象应该有不同 的访问权限的时候。
4)智能指引(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。
4. 代理设计模式
核心思路:一个接口有两个子类,1个子类完成核心业务,一个子类完成完成与核心业务有关的辅助性操作。
代码演示:
/**
* 代理模式一个接口
*/
interface Food{
void eat();
}
/**
* 代理模式核心业务处理
*/
class RealFood implements Food{
@Override
public void eat() {
System.out.println("李明吃饭,吃的很香");
}
}
/**
* 代理模式辅助业务操作
*/
class ProxyFood implements Food{
private Food food;
public Food bind(Food food){
this.food = food;
return this;
}
public void prepare(){
System.out.println("吃饭前的准备。。。。。。。");
}
public void after(){
System.out.println("吃饭后的准备。。。。。。。");
}
@Override
public void eat() {
prepare();
this.food.eat();
after();
}
}
public class Main {
public static void main(String []args){
Food proxyFood = new ProxyFood().bind(new RealFood());
proxyFood.eat();
}
}
5. 动态代理设计模式
代理类在程序运行时创建的代理方式被成为动态代理。 我们上面静态代理的例子中,代理类(studentProxy)是自己定义好的,在程序运行之前就已经编译完成。然而动态代理,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。
动态代理的简单实现:
在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象。
生成动态代理对象步骤是:
1)创建一个InvocationHandler对象
2)使用Proxy类的getProxyClass静态方法生成一个动态代理类
3) 获得动态代理类中一个带InvocationHandler参数的构造器constructor
4)通过构造器constructor来创建一个动态实例
代码演示
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface FoodDynmic{
void eat();
}
/**
* 代理模式核心业务处理
*/
class RealFoodDynmic implements FoodDynmic{
@Override
public void eat() {
System.out.println("李明吃饭,吃的很香");
}
}
/**
* 创建StuInvocationHandler类,
* 这个类中持有一个被代理对象的实例target。
* InvocationHandler中有一个invoke方法,所有执行代理对象的方法都会被替换成执行invoke方法。
* 再在invoke方法中执行被代理对象target的相应方法。
* 当然,在代理过程中,我们在真正执行被代理对象的方法前加入自己其他处理。
*
* 这也是Spring中的AOP实现的主要原理,这里还涉及到一个很重要的关于java反射方面的基础知识。
* @param <T>
*/
class FoodInvocationHandler<T> implements InvocationHandler {
//invocationHandler持有的代理对象
T target;
public FoodInvocationHandler(T target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理执行" +method.getName() + "方法");
Object result = method.invoke(target, args);
return result;
}
}
public class MainDynmic {
public static void main(String []args){
//创建被代理的实例对象
FoodDynmic foodDynmic = new RealFoodDynmic();
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler foodInvHandler = new FoodInvocationHandler<FoodDynmic>(foodDynmic);
创建一个代理对象foodDynmicProxy来代理foodDynmic,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
FoodDynmic foodDynmicProxy = (FoodDynmic)Proxy.newProxyInstance(
foodDynmic.getClass().getClassLoader(),new Class[]{FoodDynmic.class},foodInvHandler);
//代理执行吃的方法
foodDynmicProxy.eat();
}
}