码迷,mamicode.com
首页 > 编程语言 > 详细

Java基础加强——动态代理

时间:2017-05-08 23:29:41      阅读:399      评论:0      收藏:0      [点我收藏+]

标签:rri   覆盖   动态   编译   相对   nbsp   []   string   turn   

代理模式:

  为其他对象提供一种代理以控制对这个对象的访问。

  代理模式主要分为两类:

    静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。 
    动态代理:在程序运行时,运用反射机制动态创建而成

 1.静态代理相对好理解一些,来看下面的代码:

    接口 Count.java

/**
 * 账户接口
 * @author jiangbei01
 *
 */
public interface Count {
    void add();
    void update();
}

    实现类 CountImpl

package cn.test;

public class CountImpl implements Count {

    @Override
    public void add() {
        System.out.println("真实对象.add");
    }

    @Override
    public void update() {
        System.out.println("真实对象.update");
    }

}

    代理对象CountProxy.java

package cn.test;

public class CountProxy implements Count {

    //持有真实对象引用
    private CountImpl countImpl;
    //覆盖默认构造器
    public CountProxy(CountImpl countImpl) {
        super();
        this.countImpl = countImpl;
    }

    @Override
    public void add() {
        System.out.println("代理对象执行add前");
        countImpl.add();
        System.out.println("代理对象执行add后");
    }

    @Override
    public void update() {
        System.out.println("代理对象执行update前");
        countImpl.update();
        System.out.println("代理对象执行update后");
    }

}

    看看测试代码:

public class Test01 {

    public static void main(String[] args) {
        CountImpl countImpl = new CountImpl();
        CountProxy countProxy = new CountProxy(countImpl);
        countProxy.add();
        System.out.println("===========================");
        countProxy.update();
    }
}

    运行结果也容易得出:

代理对象执行add前
真实对象.add
代理对象执行add后
===========================
代理对象执行update前
真实对象.update
代理对象执行update后

  容易看出静态代理缺点:每个代理只能为一个接口服务,并且重复代码量大!

2.动态代理:java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。 

  Proxy类提供的方法:

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

其中最后一个参数 InvocationHandler h 得到InvocationHandler接口的子类实例 

  ClassLoader loader用来指明生成代理对象使用哪个类装载器,(Proxy.class.getClassLoader())

  Class<?>[] interfaces用来指明生成哪个对象的代理对象,通过接口指定,

  InvocationHandler h用来指明产生的这个代理对象要做什么事情。

  下面来看一个例子:

  先定义一个接口:Person.java

public interface Person {

    String sing(String musicName);
    String speak(String text);
}

  给出一个实现类:薛之谦 XueZhiQian.java

public class XueZhiQian implements Person {

    @Override
    public String sing(String musicName) {
        System.out.println("薛之谦唱了 "+musicName);
        return "歌曲唱完,谢谢各位!";
    }

    @Override
    public String speak(String text) {
        System.out.println("薛之谦说了 "+text);
        return "话已讲完,谢谢各位!";
    }

}

    生成代理对象的代理类:XueZhiQianProxy.java

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

public class XueZhiQianProxy {

    //要代理的对象
    private Person xzq = new XueZhiQian();
    
    public Person getProxy(){
        return (Person)Proxy.newProxyInstance(XueZhiQianProxy.class.getClassLoader(), 
                xzq.getClass().getInterfaces(), 
                new InvocationHandler() {
                    
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if(method.getName().equals("sing")){
                            System.out.println("找薛之谦唱歌需要先交2W!");
                            return method.invoke(xzq, args);
                        }
                        if(method.getName().equals("speak")){
                            System.out.println("找薛之谦唱歌需要先交10W!");
                            return method.invoke(xzq, args);
                        }
                        return null;
                    }
                });
    }
}

    测试代码:

public class Test01 {

    public static void main(String[] args) {
        XueZhiQianProxy proxy = new XueZhiQianProxy();
        Person p = proxy.getProxy();
        String s1 = p.sing("演员");
        System.out.println(s1);
        String s2 = p.speak("段子");
        System.out.println(s2);
    }
}

    测试结果:

找薛之谦唱歌需要先交2W!
薛之谦唱了 演员
歌曲唱完,谢谢各位!
找薛之谦唱歌需要先交10W!
薛之谦说了 段子
话已讲完,谢谢各位!

 

  

Java基础加强——动态代理

标签:rri   覆盖   动态   编译   相对   nbsp   []   string   turn   

原文地址:http://www.cnblogs.com/jiangbei/p/6828086.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!