关于java反射技术的一点理解:

例子参考:

http://how2j.cn/k/reflection/reflection-usage/1111.html#nowhere

概念:

关键词:运行状态;(和编译没有关系)

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

关键词:解剖

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。

对象是确实存在的事物;
类:是用来描述对象的。

反射技术获取的类名.class文件,这个文件是一个对象,用来描述这个对象的类名是Class

场景:
为什么需要用到反射技术,或者说使用反射技术的好处是什么?
有三个应用程序:Test.java
Service1.java
Service2.java

1、 写好了一个Java应用程序,比如Test.java;项目初期调用service1.java中的方法,

public class Test {
  public static void main(String[] args) {
     new Service1().doService1();
  }
}

后来项目需求发生了变化,需要添加新的功能,一种方法直接在Test代码中修改,添加新的代码,这种操作不太好,就是改源码这种方式是个比较伤的方法,如果后期代码又变,又需要改源码,改源码需要做两件事,第一步看懂之前的源码,第二步添加功能;还不如重新写一段代码,然后再用进去;
接下来我们重新写一段代码,命名为service2.java ;
这个时候如果Test.java要使用service2.java,必须先把service1的调用代码注释掉,再修改代码:

public class Test {
    public static void main(String[] args) {
//      new Service1().doService1();
        new Service2().doService2();
    }
}

但是前面说过了,这样处理还是改动到了Test.java的源码,虽然把新功能封装到了service2.java中,还是没有改变实际的不改动源码而添加新功能的需求;
这个时候反射就上场了。

2、使用反射方式,首先准备一个配置文件,就叫做spring.txt吧, 放在src目录下。 里面存放的是类的名称,和要调用的方法名。
在测试类Test中,首先取出类名称和方法名,然后通过反射去调用这个方法。

当需要从调用第一个业务方法,切换到调用第二个业务方法的时候,不需要修改一行代码,也不需要重新编译,只需要修改配置文件spring.txt,再运行即可。

这也是Spring框架的最基本的原理,只是它做的更丰富,安全,健壮。
Spring.txt

class=reflection.Service1
method=doService1

Test.java

package reflection;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;

public class Test {

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) throws Exception {

        //从spring.txt中获取类名称和方法名称
        File springConfigFile = new File("e:\\project\\j2se\\src\\spring.txt");
        Properties springConfig= new Properties();
        springConfig.load(new FileInputStream(springConfigFile));
        String className = (String) springConfig.get("class");
        String methodName = (String) springConfig.get("method");

        //根据类名称获取类对象
        Class clazz = Class.forName(className);
        //根据方法名称,获取方法对象
        Method m = clazz.getMethod(methodName);
        //获取构造器
        Constructor c = clazz.getConstructor();
        //根据构造器,实例化出对象
        Object service = c.newInstance();
        //调用对象的指定方法
        m.invoke(service);

    }
}

好处:这样一来我们就达成了不用改动Test.java源码,就能使用到新功能的目的,只需要改动配置文件,这个改动还是可以接受的。

这里面就是用到了反射技术,Java把service1.java和service2.java代码进行解剖,Test,java去找反射,反射去找对应的解剖的service1.java和service2.Java,根据配置文件找对应的代码,找到之后,反射解剖拿出对应的类的方法名称。

猜你喜欢

转载自blog.csdn.net/happy_bigqiang/article/details/79614245
今日推荐