Java代理模式

Java代理模式

    代理可以分为:静态代理(StaticProxy)和动态代理(DynamicProxy)。

代理概念

    为某个对象提供一个代理,以控制这个对象的访问。代理类和委托类有共同的父类和父接口,这样在任何使用委托类对象的地方都可以使用代理对象代替。代理类负责请求的预处理、过滤、将请求分派给委托类处理以及委托类执行完请求后后的后续处理。代理分为了静态代理动态代理

    个人感觉代理这种模式汲取了继承和组合的优点,即没有暴露委托类的任何敏感信息,又能通过运用组合来实现较多的功能。至于委托类和代理类实现共同的接口(也就是所谓的代理接口),目的是为了让用户用起来觉得根本不存在中间的代理类。(就好像一些中介机构做的很隐蔽,让用户和主人之间感觉没有第三方一样)。

静态代理

    图解中的Client即调用接口的一方,代理接口(Subject)、委托类(RealSubject)、代理类(ProxySubject),通过代理类来和用户交流。下面用一个小故事来说明代理模式:A君有一套房子需要出售,由于买家不好找就直接挂在了B君的代售公司,过一段时间买家C君直接就把房子买走了。看下面的代码实现:

interface sell {
public void sellHouse();
}

class PersonA implements sell{

public void sellHouse() {
    System.out.println("RealSubject...SellHouse...");
}
}

class PersonB implements sell{

//代理君B持有一个真实类(房主A)的实例,可以想象类似成留了一个电话号码,有人来买房子就立马通知
PersonA a = new PersonA();

public void sellHouse() {
    //有人来买房就立马通知真实类(房主A)...
    a.sellHouse();
    System.out.println("Proxy...SellHouse...");
}
}

public class JavaTest{
public static void main(String[] args) {
    //我就相当于是买房子的C君
    PersonB b = new PersonB();
    //我直接找代理B君买房子
    b.sellHouse();
}
}

运行结果为:
RealSubject...SellHouse...
Proxy...SellHouse...

    至于真实类和代理类需要实现同样的一个接口,小达认为统一接口能让客户端在用到真实类对象的地方都能够替换成代理类,不用改变其调用的方法。因为在这里调用类完全不可以实现接口,利用组合的特性持有真实类的对象,通过自定义几个方法直接调用真实类的方法,这样暴露给外界的接口即是代理类自定义的一些接口了。

动态代理

    JDK 5中引入的动态代理机制,允许开发人员在运行时刻动态的创建出代理类及其对象。在运行时刻,可以动态的创建出一个实现了多个接口的代理类。

    说道动态代理,就不得不涉及到java.lang.reflect.Proxy类,这是Java动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态的生成代理类及其对象。

    每个代理类的对象都会关联一个表示内部处理逻辑的InvocationHandler接口的实现。使用者调用了代理对象所代理的接口中的方法的时候,这个调用的信息会被传递给InvocationHandlerinvoke方法。在invoke方法的参数中可以获取到代理对象、方法对应的Method的对象和调用的实际参数,最后invoke方法执行的结果将被返回给调用者。这种做法实际上是对方法调用的拦截。

    简单的来说,真实类在运行之前都不知道自己的代理类是谁,在运行期间通过反射来动态的生成一个代理类并为真实类做代理。下面又有个小故事(纯属虚构,小朋友们不要学坏…..)来辅助理解:A君(真实类)马上要考试了,但自己实力不够,于是想找人代考(即找自己的代理类,在找到之前不知道自己的代理类是谁),接着通过B君(相当于InvocationHandler,用于分发调用请求)的介绍,找到了一只学霸君(相当于动态生成的代理类,并不知道是谁)帮助代考。实现的代码如下:

interface Exam {
public void findHelp();
}

class PersonA implements Exam{
public void findHelp() {
    System.out.println("PersonA...find...help...");
}
}

/**
* 这个类就相当于是B君,为A君动态的创建代理类对象
*/
class MyInvocationHandler implements InvocationHandler {

private Object targetObject;

public Object newProxyInstance(Object o) {

    //targetObject是真实类的对象,就相当于是A君
    targetObject = o;

    /*
     * 在这里动态的为传入的真实对象o动态的创建了一个代理类,也就是我们说的学霸君
     * 最后一个参数this指的是处理调用拦截的Handler
     */
    return Proxy.newProxyInstance(
            targetObject.getClass().getClassLoader(), 
            targetObject.getClass().getInterfaces(), 
            this);
}

/**
 * 在调用的时候拦截调用方法,然后做相的处理
 */
@Override
public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
    return method.invoke(targetObject, args);
}

}
public class JavaTest{
public static void main(String[] args) {
    PersonA a = new PersonA();
    MyInvocationHandler mih = new MyInvocationHandler();
    //为A君动态生成代理类
    Exam e = (Exam) mih.newProxyInstance(a);
    e.findHelp();
}
}
Java代理模式是一种结构型设计模式,其目的是为其他对象提供一种代理以控制对这个对象的访问。代理对象可以在客户端和目标对象之间充当中介,以便于客户端访问目标对象时,可以在不改变目标对象的情况下添加一些额外的功能,比如安全性、远程访问、缓存等。 在Java中,代理模式可以通过两种方式实现:静态代理动态代理。静态代理需要手动编写代理类,而动态代理可以在运行时通过反射机制动态生成代理类,更加灵活。 举个例子,假设我们有一个接口`Subject`,其中定义了一些方法。我们希望在调用这些方法时,增加一些额外的日志记录功能。我们可以编写一个代理类`SubjectProxy`,在代理类中实现接口方法并调用目标对象的方法,同时在方法前后添加日志记录的代码。客户端则通过代理类访问目标对象。 静态代理示例代码如下: ```java public interface Subject { void doSomething(); } public class RealSubject implements Subject { @Override public void doSomething() { System.out.println("RealSubject do something."); } } public class SubjectProxy implements Subject { private Subject realSubject; public SubjectProxy(Subject realSubject) { this.realSubject = realSubject; } @Override public void doSomething() { System.out.println("Before do something."); realSubject.doSomething(); System.out.println("After do something."); } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); Subject subjectProxy = new SubjectProxy(realSubject); subjectProxy.doSomething(); } } ``` 动态代理示例代码如下: ```java public class SubjectHandler implements InvocationHandler { private Object target; public SubjectHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before " + method.getName()); Object result = method.invoke(target, args); System.out.println("After " + method.getName()); return result; } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); InvocationHandler handler = new SubjectHandler(realSubject); Subject subjectProxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler); subjectProxy.doSomething(); } } ``` 无论是静态代理还是动态代理代理模式都可以在不改变目标对象的情况下,为其添加额外的功能,提高代码的可复用性和灵活性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值