Java静态代理与动态代理

有的时候类 A A 可能无法访问类B,但是有一个类 C C ,它可以访问A B B 也能访问到C,那么 A A 就可以通过C间接的访问到 A A

在Java**代理模式**中中三类角色:

  1. 抽象角色,定义一系列的行为方法,可以用接口或者抽象方法表示。
  2. 真实角色,它才真正做事的角色。
  3. 代理角色,代理角色持有真实角色的一个引用,当访问代理角色时,它可以帮助我们间接的访问到真实角色(情况时,我们无法直接访问真实角色)。代理对象提供与真实角色对象相同的接口,以便完全代替真实角色。当我们操纵代理对象的行为时,它则会进而操纵其引用真实对象相应的行为。代理对象可以在操纵真实对象的行为时附加自己的行为动作。

下面以一个到中介租房的理解来理解Java的静态代理模式:

首先定义一个租房的接口抽象角色

/*
 * 定义给一个租房子的接口
 */
public interface Rent {

    public void rent();

}

定义一个房东类 真实角色,它继承了实现了抽象角色定义的行为

/*
 * 定义房东类,有一个租房子的方法
 */
public class Landlord implements Rent {

    @Override
    public void rent() {
        System.out.println("房东出租房子");

    }

}

定义一个中介类 代理角色,其内部持有一个房东的引用。

/*
 * 中介类,由于你找不到房主,因此你只能找中介帮你租房子
 * 因此他也有一个租房子的方法,中介不是活雷锋,因此它会在
 * 执行租房方法的时候进行一些与租房本相关的利益活动
 */
public class Agency implements Rent {
    //代理角色持有对真实角色的引用,相当于中介手中的房源
    private Landlord landlord;

    /*
     * 中介的租房行为
     */
    @Override
    public void rent() {
        this.before();
         if(this.landlord==null) {
             landlord = new Landlord();
         }

         landlord.rent();
         this.after();
    }
    /*
     * 中介自己的行文
     */
    public void before() {
        System.out.println("查找房源");
    }
    /*
     * 中介自己的行文
     */
    public void after() {
        System.out.println("索要中介费");
    }

}

一个测试类:

public class Person {
    public static void main(String[] args) {
        /*
         * 找不到房源,因此只能求助中介租房
         */
        Agency agency = new Agency();
        agency.rent();
    }

}

结果为:

查找房源
房东出租房子
索要中介费

从上面可以看出,每一个真实角色就需要一个代理角色,如果用静态代理的话,会导致类的急剧膨胀,因此显示了动态代理的必要性。

下面看一个动态代理类的实例,其中定义了两个真实角色的类,只要修改一下真实角色即可实现代理类对多个真实类的代理。

  1. 首先定义一个接口
package com.org.dynamicProxy;
/*
 * 抽象角色类,定义一些方法
 */
public interface Subject {
    public void dosomething() ;
}
  1. 定义两个真实角色
package com.org.dynamicProxy;

public class RealSubject1 implements Subject {

    @Override
    public void dosomething() {
        System.out.println("这个方法来自于RealSubject1");

    }

}
package com.org.dynamicProxy;

public class Realsubject2 implements Subject {

    @Override
    public void dosomething() {
        System.out.println("这个方法来自于RealSubject2");

    }

}
  • handler类
package com.org.dynamicProxy;

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

public class CommonInvocationHandler implements InvocationHandler{
    /*
     * target变量持有真实角色对象的应用,因为动态代理类可以
     * 代理所有对象,因此定义为Object类型的。
     */
    private Object target;



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

    public CommonInvocationHandler() {

    }

    public CommonInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /*
         * 1、这里相当于反射中调用method方法来执行,相当于
         * method.invoke(对象,new Object[]{参数})
         * 只不过java底层已经为我们完成了创建method的过程。
         * 2、定义一个result只是增强通用性,我们定义的类的方法并没有返回值
         */
        Object result = method.invoke(target, args);

        return result;
    }

}

测试类:

package com.org.dynamicProxy;

import java.lang.reflect.Proxy;

public class Client {

    public static void main(String[] args) {
        RealSubject1 realSubject1 = new RealSubject1();
        /*
         * 生成handler
         */
        CommonInvocationHandler handler = new CommonInvocationHandler();

        handler.setTarget(realSubject1);

        Subject  proxy = null;

        /*
         * 1、生成代理类的实例,proxy相当于前面的中介类生成的实例
         * 动态代理与静态代理不太相同的是,静态代理中代理类会直接去执行行为
         * 但是在动态代理中,代理对象将执行行为这项操作又委托给hanler去做了
         * 2、newProxyInstance是生成代理实例的方法其中第一个参数为类加载器,
         * 我们写接口的类加载器就行
         * 第二个参数为代理类要实现接口的列表
         * 第三个参数为hanlder
         */
        proxy = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(), 
                new Class[] {Subject.class}, handler);
        /*
         * 执行行为
         */
        proxy.dosomething();
        System.out.println("-----------------------------------------");
        /*
         * 代理另一个对象
         */
        Realsubject2 realsubject2= new Realsubject2();

        handler.setTarget(realsubject2);
        /*
         * 创建代理类的实例
         */
        proxy = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(), 
                new Class[] {Subject.class}, handler);

        proxy.dosomething();

    }

}

执行结果

这个方法来自于RealSubject1
-----------------------------------------
这个方法来自于RealSubject2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值