动态代理模式(常用用法)

动态代理模式

实现原理

  • 设计动态代理类(DynamicProxy)时,不需要显式实现与目标对象类(RealSubject)相同的接口,而是将这种实现推迟到程序运行时由 JVM来实现

即:在使用时再创建动态代理类 & 实例静态代理则是在代理类实现时就指定与目标对象类(RealSubject)相同的接口

  • 通过Java 反射机制的method.invoke(),通过调用动态代理类对象方法,从而自动调用目标对象的方法
//动态代理模式例子之一
//租房
public interface Rent {
    public void rent();
}

//房东
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东出租房子");

    }
}

//用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    private Rent rent;

    public void setRent(Rent rent)  {
        this.rent = rent;
    }

    //生成得到代理类
   public Object getProxy(){
       return  Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
   }

    //处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质就是使用反射机制来实现
        seeHouse();
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }

    public void seeHouse(){
        System.out.println("房东带去看房子");
    }
    public void fare(){
        System.out.println("收中介费");
    }
}

//用户类
public class Client {
    public static void main(String[] args) {
        //真实角色
        Host host = new Host();
        //动态代理类
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        //通过调用程序处理角色来处理我们要调用的接口对象
        proxyInvocationHandler.setRent(host);
        Rent proxy = (Rent) proxyInvocationHandler.getProxy();//这里的proxy动态生成
        proxy.rent();
    }
}
结果:
房东带去看房子
房东出租房子
收中介费

此程序不是常规的动态代理,只是给我们展示了大致动态代理的原理,通过反射机制调用

目标对象.

动态代理模式例子二

//功能接口
public interface UserService
{
    public void add();
    public void delete();
    public void update();
    public void query();
}

//实现类
public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }

    @Override
    public void delete() {
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
        System.out.println("修改了一个用户");
    }

    @Override
    public void query() {
        System.out.println("查询了一个用户");
    }
}

//用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    public void setRent(Object target)  {
        this.target = target;
    }

    //生成得到代理类
   public Object getProxy(){
       return  Proxy.newProxyInstance(this.getClass().getClassLoader(),
               target.getClass().getInterfaces(), this);
   }

    //处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质就是使用反射机制来实现
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }
    public void log(String msg)
    {
        System.out.println("执行了"+msg+"方法");
    }
}

//用户类
public class Client {
    public static void main(String[] args) {
        //真实角色
        UserServiceImpl userService = new UserServiceImpl();
        //动态代理类
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        proxyInvocationHandler.setTarget(userService);
        //动态生成代理类
        UserService proxy = (UserService) proxyInvocationHandler.getProxy();
        proxy.delete();
    }

}
结果:
执行了delete方法
删除了一个用户

相比例子1,例子2的用法适用于所有情况,可以当做模板参考.

代理模式绝对不止于此

在这个场景中:我把账号托给代打平台,平台帮我找到代打者,然后把号给他,但同时,真实角色也要知道代理角色的信息等等,所以,代理模式运用很广泛,在框架里几乎无处不在,非常符合AOP切面编程.

在过去主打纵向编程的时代,切面编程在开发中也越来越重要.

优点

  • 只需要1个动态代理类就可以解决创建多个静态代理的问题,避免重复、多余代码
  • 更强的灵活性

设计动态代理类(DynamicProxy)时,不需要显式实现与目标对象类(RealSubject)相同的接口,而是将这种实现推迟到程序运行时由 JVM来实现在使用时(调用目标对象方法时)才会动态创建动态代理类 & 实例,不需要事先实例化

缺点

  • 效率低
    相比静态代理中 直接调用目标对象方法,动态代理则需要先通过Java反射机制 从而 间接调用目标对象方法
  • 应用场景局限
    因为 Java 的单继承特性(每个代理类都继承了 Proxy 类),即只能针对接口 创建 代理类,不能针对类 创建代理类

即只能动态代理 实现了接口的类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值