Java笔记 – 反射 动态代理
本文由发表于4年前 | J2EE | 评论数 1 |  被围观 3,796 views+
反射:运行时的类信息RTTI与反射的区别:动态代理:

20131227-java001

反射:运行时的类信息

如果不知道某个对象的确切类型,RTTI可以告诉你,但是前提是在编译时必须已知,这样才能使用RTTI识别它,并利用这些信息做一些有用的事情。也就是在编译时,编译器必须知道所有要通过RTTI来处理的类。

考虑这种情况:假设你获取了一个指向某个并不在你程序空间中的对象的引用,这个时候,在编译时,程序就无法获取到这个对象所属的类。

这个时候反射就登场啦。反射提供了一种机制,用来检查可用的方法,并返回方法名。另外,在这种情况下我们也会需要在运行时获取类的信息:希望提供在跨网络的远程平台上创建和运行对象的能力。

反射机制的支持类:Class类与java.lang.reflect类库一起对反射的概念进行了支持,这个类库包含了Field,Method以及Constructor类(每个类都实现了Member接口)。这些类都是JVM运行时创建的,用于表示未知类里对应的成员。

使用Constructor创建新对象,用get()和set()方法读取和修改与Field对象关联的字段,用invoke()方法调用与Method对象关联的方法。另外,还可以调用getFields(),getMethods()和getConstructors()等方法,返回表示字段,方法以及构造器的对象数组。

这里推荐几篇反射的文章:

反射机制的介绍和基本的API的使用

通过反射机制动态创建和访问数组

通过反射机制修改类中的私有属性的值

通过反射机制动态获取属性的值模拟Struts的自动赋值

RTTI与反射的区别:

RTTI:编译器在编译时打开和检查.class文件,也就是说我们可以用普通的方式调用对象的所有方法。

反射机制:.class文件在编译时是不可获取的,所以是在运行时打开和检查.class文件的。

反射机制的更多用途:通常你是不需要使用反射的,但是它们在你需要创建更加动态的代码时会很有用。反射机制用来支持其他的特性如对象序列化,JavaBean。

动态代理:

代理是基本的设计模式之一。关于代理模式,这里有一篇文章:

设计模式笔记 – Proxy 代理模式 (Design Pattern)

Java的动态代理比代理的思想更向前迈进了一步,因为它可以动态的创建代理并动态的处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的策略。

下面来看一个Java中实现动态代理的例子:

首先创建抽象角色:

public interface Subject {
    void doSomething();
    void somethingElse(String arg);
}

接下来创建具体角色:

public class RealSubject implements Subject{

    @Override
    public void doSomething() {
        System.out.println("doSomething");
    }

    @Override
    public void somethingElse(String arg) {
        System.out.println("somethingElse: " + arg);
    }
}

接下来是创建一个InvocationHandler接口的实现:

public class DynamicProxyHandler implements InvocationHandler{

    private Object proxied;

    public DynamicProxyHandler(Object proxied){
        this.proxied = proxied;
    }

    /**
     * invoke()方法中传递进来了代理对象,以防你需要区分请求的来源
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("*** proxy ***" + proxy.getClass());
        System.out.println("*** method ***" + method);
        System.out.println("*** args ***" + args);
        // 可以在这里做一些处理,如查看方法名,查看方法签名的其他方面,甚至可以搜索特定的参数值
        if(method.getName().equals("interesting"))
            System.out.println("Proxy detected the interesting method.");
        // 将请求转发给被代理对象,并传入必须的参数
        return method.invoke(proxied, args);
    }

}

最后在main方法中创建动态代理对象,并通过动态代理调用真实角色的方法:

public class SimpleDynamicProxy {

    public static void consumer(Subject subject){
        subject.doSomething();
        subject.somethingElse("haha~~");
    }

    public static void main(String[] args){
        // 创建真实的对象
        RealSubject real = new RealSubject();
        consumer(real);
        // 通过调用该方法创建动态代理
        Subject proxy = (Subject)Proxy.newProxyInstance(
                Subject.class.getClassLoader(), // 类加载器
                new Class[]{Subject.class}, // 你希望该代理实现的接口列表
                new DynamicProxyHandler(real));  // InvocationHandler接口的一个实现
        consumer(proxy);
    }
}

第一个consumer(real)输出为:

doSomething
somethingElse: haha~~

第二个consumer(proxy)输出为:

*** proxy ***class $Proxy0
*** method ***public abstract void com.itzhai.javanote.entity.Subject.doSomething()
*** args ***null
doSomething
*** proxy ***class $Proxy0
*** method ***public abstract void com.itzhai.javanote.entity.Subject.somethingElse(java.lang.String)
*** args ***[Ljava.lang.Object;@1a1c887
somethingElse: haha~~

动态代理可以将所有调用重定向到调用处理器,因此通常会向调用处理器传递一个真实对象的引用,从而使得调用处理器在执行其中介任务时,可以将请求转发。如上面的创建DynamicProxyHandler对象时就传入了真实的角色。

下面是一篇关于Java动态代理的文章:

Java基础笔记 – 动态代理 Java中动态代理类的介绍和使用

除了文章中有特别说明,均为IT宅原创文章,转载请以链接形式注明出处。
本文链接:http://www.itzhai.com/java-notes-reflection-dynamic-proxies.html
关键字: , , ,
arthinking Java技术交流群:280755654,入门群:428693174 more
分享到:
 
2013 12/25
如果您有更好的原创技术博文或者观点,欢迎投稿:admin@itzhai.com,或者关注订阅左侧浮动面板的微信号订阅IT宅itread)发送消息。
文章评论
    一条评论
给我留言

有人回复时邮件通知我
J2EE的相关文章
随机文章 本月热门 热评
1 Struts2笔记 – 命名空间和Action的三种创建方法 2011/6/18
2 Semaphore的介绍和使用 2012/7/30
3 Java虚拟机笔记 – JVM 类的加载、连接和初始化 手动加载类 2011/11/4
4 SVN版本管理工具的安装设置与使用 2011/11/30
5 一些常用的音乐英语词汇 2012/10/22
6 【吉他曲子学习资源】Kotaro Oshio: wings you are the hero 2012/1/2
友情推荐 更多
破博客 文官洗碗安天下,武将打怪定乾坤。多么美好的年代,思之令人泪落。
Mr.5's Life 白天是一名程序员,晚上就是个有抱负的探索者
行知-追寻技术之美 关注大数据,分布式系统
我爱编程 编程成长轨迹
Cynthia's Blog 学习笔记 知识总结 思考感悟
 
猜您喜欢
欢迎关注我的公众号 IT宅
关于IT宅 文章归档

IT宅中的文章除了标题注明转载或有特别说明的文章,均为IT宅的技术知识总结,学习笔记或随笔。如果喜欢,请使用文章下面提供的分享组件。转载请注明出处并加入文章的原链接。 感谢大家的支持。

联系我们:admin@itzhai.com

Theme by arthinking. Copyright © 2011-2015 IT宅.com 保留所有权利.