Java中的代理

代理模式

在设计模式中存在的代理模式;代理模式的作用就是为其他对象提供一种代理以控制对这个对象的访问。

代理模式一般存在三种角色:抽象角色,代理角色,真实角色;百度百科上摘抄了三种角色的解释:

抽象角色:通过接口或抽象类声明真实角色实现的业务方法。

代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。

真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

代理模式的优点:一是可以隐藏委托类(真实角色)的实现,二是可以实现客户和委托类之间的解耦;

Java中的代理

在java中代理分静态代理和动态代理;所谓静态代理是在程序运行前代理类就已经存在的,一般这种代理类都是通过我们自己定义的java类来实现;动态代理相对就麻烦一些,是在程序运行时生成代理类;是通过我们在Java代码来动态生成的;

现在有个场景:火车站售票,有些代理点也可以买票,在这里火车票代理点就是代理角色;

首先把卖票抽象成一个接口:

public interface iTicketService {

    void SellTicket(String name);
}

火车站卖票实现这个接口:

public class trainStation implements iTicketService {
    public void SellTicket(String name) {
        System.out.println(name + "成功购买了一张票");
    }
}

静态代理

静态代理就是在java代码中我们自己定义代理类;代理类中持有委托类的引用;并且代理类也实现了和委托类一样的接口;

public class stationProxy implements iTicketService {
    private iTicketService TicketService;

    public stationProxy(iTicketService ticketService) {
        this.TicketService = ticketService;
    }

    public void SellTicket(String name) {
        System.out.println("代售点开始卖票");
        this.TicketService.SellTicket(name);
        System.out.println("代售点卖票成功");
    }
}

从代码中我们可以看到代理的好处,代理内部还是调用委托类的方法,我们在调用委托类的方法前或是方法后可以来进行一些相关操作;

静态代理的调用也非常的简单:

iTicketService ticketService=new trainStation();
stationProxy station=new stationProxy(ticketService);
station.SellTicket("张三");

输出:

代售点开始卖票

张三成功购买了一张票

代售点卖票成功

动态代理

动态代理相对于静态代理的区别就在于代理类是在运行时生成的;动态代理的优势就在于可以方便的对代理类的函数统一的管理,而不用一个个的去修改代理函数,当代理非常多的时候,动态代理的优势就很多大了;

InvocationHandler

在使用动态代理时,需要我们定义一个代理类和委托类之间关联的中介类,在java中这个中介类应该实现InvocationHandler接口;
public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
}

在InvocationHandler接口中只有一个invoke方法,当代理类执行代理方法都会通过invoke方法来执行;proxy:代理类对象,method 需要执行的代理方法;args代理方法执行的参数,方法的返回值object也就是代理方法的返回值,我们可以在invoke方法内添加统一的处理逻辑;比如火车票代售点我们可以创建动态的代理类:

public class dynamicProxy implements InvocationHandler {
    private  iTicketService TicketService;
    public dynamicProxy(iTicketService ticketService){
        this.TicketService=ticketService;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("动态代理开始卖票");
        Object obj= method.invoke(TicketService,args);
        System.out.println("动态代理卖票结束");
        return  obj;
    }
}

从dynamicProxy类来看,我们的代理类也持有委托类的一个实例,在 invoke中采用反射进行方法的执行;

在JAVA中实现了InvocationHandler接口的动态代理类需要借助Proxy获取实例

  dynamicProxy dynamicProxy=new dynamicProxy(ticketService);
   Class<?>[] interfaces=new  Class<?>[]{iTicketService.class};
   System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
   iTicketService ticketproxy=(iTicketService)Proxy.newProxyInstance(iTicketService.class.getClassLoader(),interfaces,dynamicProxy);
   ticketproxy.SellTicket("李四");

在Proxy类中通过newProxyInstance来获取代理类的实例;

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)

在newProxyInstance方法中ClassLoader是代理加载类,interfacess数组是类实现的接口数组,h就是我们自己定义的中介类了

通过System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");方法会产生一个$Proxy0.class文件,这个文件即为动态生成的代理类文件;

我们可以看下生成的代理类:

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

public final class $Proxy0 extends Proxy implements iTicketService {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void SellTicket(String var1) throws  {
        try {
            super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final int hashCode() throws  {
        try {
            return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m3 = Class.forName("iTicketService").getMethod("SellTicket", new Class[]{Class.forName("java.lang.String")});
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

在生成的代理类中m3就是我们的接口定义的SellTicket方法,内部还是调用了InvocationHandler接口中的invoke方法;

 
时间: 2024-08-26 17:26:57

Java中的代理的相关文章

java中设置代理的两种方式

1 前言 有时候我们的程序中要提供可以使用代理访问网络,代理的方式包括http.https.ftp.socks代理.比如在IE浏览器设置代理. 那我们在我们的java程序中使用代理呢,有如下两种方式.直接上代码. 2 采用设置系统属性 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import jav

Object-c和Java中的代理

代理模式的核心思想就是一个类想做一个事(函数),但它不去亲自做(实现),委托别的类(代理类)来完成.代理模式Java和oc中都有很广泛的应用,好处颇多,以下是简单的介绍和小例子. 代理模式的优点: 1.可以实现传值,尤其是当一个对象无法直接获取到另一个对象的指针,又希望对那个变量进行一些操作时.(这点在ios里面应用颇多) 2.实现了代码的解耦.可以对外提供接口,具体的工作由不同的客户来决定怎么做. 下面分别对ios和java中的代理模式简单说明 IOS的代理模式,分两步: 1.在委托类A声明一

Java中的代理模式

1.什么是代理模式 代理模式:就是为其他对象提供一种代理以控制对这个对象的访问. 代理可以在不改动目标对象的基础上,增加其他额外的功能(扩展功能). 举个例子来说明代理的作用: 一般我们想邀请明星来当我们的代言人,我们并不能直接联系到明星,而是通过其经纪人,来告诉经纪人我们需要和明星进行合作,然后通过经纪人来转达给明星.,明星只需要做好代言工作就好,其他繁琐的事情就交于经纪人就可以.这里的经经纪人就是一个代理对象,明星就是一个目标对象. 用图表示如下: 2.三种代理模式  2.1 静态代理 静态

java中动态代理实现机制

JAVA各种动态代理实现的比较 接口 interface AddInterface{ int add(int a, int b); } interface SubInterface{ int sub(int a, int b); } 实现类 class Arithmetic implements AddInterface, SubInterface{ @Override public int sub(int a, int b) { return a-b; } @Override public i

java中动态代理

一.在java中怎样实现动态代理 1.我们要有一个接口,还要有一个接口的实现类,而这个实现类呢就是我们要代理的对象 接口: 1 package org.dynamicproxy.test; 2 3 public interface UserDao { 4 public void addUser(User user); 5 } 接口的实现类(即要代理的对象): 1 package org.dynamicproxy.test; 2 3 public class UserDaoMysqlImpl im

Java中动态代理方式:

JDK中生成代理对象的API 代理类所在包:java.lang.reflect.ProxyJDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是: static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h ) 注意该方法是在Proxy类中是静态方法,且接收的三个参数依次为: ClassLoader loader,:指定当

java中静态代理和动态代理

一.概述 代理是一种模式,提供了对目标对象的间接访问方式,即通过代理访问目标对象.如此便于在目标实现的基础上增加额外的功能操作,前拦截,后拦截等,以满足自身的业务需求,同时代理模式便于扩展目标对象功能的特点也为多人所用. 按照代理的创建时期,代理类可以分为两种: 静态:由程序员创建代理类或特定工具自动生成源代码再对其编译.在程序运行前代理类的.class文件就已经存在了. 动态:在程序运行时运用反射机制动态创建而成. 我们根据加载被代理类的时机不同,将代理分为静态代理和动态代理.如果我们在代码编

Java中动态代理技术生成的类与原始类的区别 (转)

用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后来定义的逻辑.这样就达到了动态的在原有类上增加一些功能.比如日志打印,拦截信息等. 这里只关心动态代理技术生成新的类,先不管虚拟机是如何去生成类,用了什么字节码生成技术,怎么产生字节码等这一系列动作.现在只关心最后生成的新类长什么样,它和老类有什么区别.为了获取到生成后的代理类的字节码并且反编译成我

Java中动态代理实现原理深究

一.前言 笔者平时开发使用"动态代理"不多,最近在看设计模式的时候,"动态代理"又在面前晃了几次,所以这次想从源码的角度去分析动态代理的实现原理,以窥探其精妙~ 二.正文 2.1 静态代理  本文源码基于:jdk1.6.0_33 在正式剖析动态代理的源码之前,我们可以先来看看"静态代理"(就是我们普通的代理模式)的UML图: 从上图可以看出,代理类"ProxySubject"和被代理类"RealSubject&quo