美文网首页
JavaSE学习笔记——反射

JavaSE学习笔记——反射

作者: funOfFan | 来源:发表于2020-03-04 10:38 被阅读0次
    • Java Reflection
      1. 反射是动态语言实现的关键
      2. 发射机制允许在执行期间借助Reflection API取得任何类的内部信息,
        并直接操作任意对象的内部属性及方法
    • Java反射机制提供的功能
      1. 在运行时候判断任意一个对象所属的类
      2. 在运行时构造任意一个类的对象
      3. 在运行时判断任意一个类所具有的成员变量和方法
      4. 在运行时调用任意一个对象的成员变量和方法
      5. 生成动态代理
    • 如何创建Class的实例(重点)
      /**
      * java.lang.Class:是反射的源头
      * 我们创建了一个类,通过编译,生成对应的.class文件,
      * 之后使用java.exe加载此文件(JVM的类加载器完成)
      * 此文件加载到内存以后,就是一个运行时类,存放在缓存区
      * 那么该运行时类本身就是一个大的Class的实例
      */
      //1.调用运行时类本身的.Class属性
      Class c1 = Person.class;
      //2. 通过运行时类的对象获取
      Person p = new Person();
      Class c3 = p.getClass();
      //3.通过Class的静态方法获取
      String class_name = "learning_reflect.Person";
      Class c4 = Class.forName(class_name);
      //4.通过类的加载器
      ClassLoader cl = this.getClass().getClassLoader();
      Class c5 = cl.loadClass(class_name);
      
    • 有了Class类实例之后,可以做什么?
      1. 从Class类实例,创建运行时类的对象
      //方法一,调用Class类的newInstance方法,直接创建运行时对象
      Class clazz = Class.forname("learning_reflect.Person");
      Object obj = clazz.newInstance();
      Person p = (Person) obj;
      
      //方法二,调用指定的构造器,创建运行时对象
      Class clazz = Person.Class;
      Constructor cons = clazz.getDeclaredConstructor(String.Class,int.Class);
      cons.setAccessible(true);
      Person p = (Person)cons.newInstance("Tom", 10);
      
      1. 获取对应的运行时类的完整类结构:属性、方法、构造器、所在包、父类、接口、
        泛型、注解、异常、内部类
      //举例如下
      //getMethods方法获取运行时类及其父类中所有声明为public的方法
      Method[] m1 = clazz.getMethods();
          
      //getDeclaredMethods方法获取运行时类自身声明的所有方法,但不包含父类的
      Method[] m2 = clazz.getDeclaredMethods();
      
      1. 可以调用运行时类中指定的结构(方法、属性、构造器等)
      //调用指定非静态方法
      Class clazz = Person.class;
      Method m1 = clazz.getMethod("show");
      Person p = (Person) clazz.newInstance();
      Object returnValue = m1.invoke(p);//This is a person
      //调用指定静态方法
      Method m3 = clazz.getMethod("info");
      m3.invoke(Person.class);
      
      //调用指定构造器
      String classname = "learning_reflect.Person";
      Class clazz = Class.forName(classname);
      Constructor cons = clazz.getDeclaredConstructor(String.class, int.class);
      cons.setAccessible(true);
      Person p = (Person) cons.newInstance("罗维", 20);
      
      1. 动态代理-反射的应用,体会反射的动态性
    • 代理设计模式的原理:
      1. 使用一个代理将对象包装起来,然后用该代理取代原始对象,
        任何对原始对象的调用都要通过代理,
        代理决定是否以及何时将方法调用转移到原始对象上。
      2. 静态代理:要求被代理类和代理类同时实现相应的一组接口;
        通过代理类的对象调用重写接口的方法时,实际上执行的是被代理类的同样的方法。
      3. 动态代理:在程序运行时,根据被代理类及其实现的接口,动态的创建一个代理类,
        当调用代理类的实现的抽象方法时,就发起对被代理类同样方法的调用。
        • 提供一个实现了InvocationHandler接口实现类,并重写其invoke方法
        • Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),h);
          (此处obj为被代理类对象,h为实现了InvocationHandler的一个对象)
    • 动态代理与AOP
      package learning_reflect;
      
      import java.lang.reflect.InvocationHandler;
      import java.lang.reflect.Method;
      import java.lang.reflect.Proxy;
      
      interface Human {
          void info();
      
          void fly();
      }
      
      class SuperMan implements Human {
          @Override
          public void fly() {
              System.out.println("Here comes Clerk");
          }
      
          @Override
          public void info() {
              System.out.println("I am Super Man");
          }
      }
      
      class HumanUtil {
          public void method1() {
              System.out.println("===方法一===");
          }
      
          public void method2() {
              System.out.println("===方法二===");
          }
      }
      
      class SelfInvocationHandler implements InvocationHandler {
          Object obj;//被代理对象的声明
      
          public void setObject(Object obj) {
              this.obj = obj;
          }
      
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              HumanUtil h = new HumanUtil();
              h.method1();
              Object returnVal = method.invoke(obj, args);
              h.method2();
              return returnVal;
          }
      }
      
      class MyProxy {
          //动态地创建一个代理类的对象
          public static Object getProxyInstance(Object obj) {
              SelfInvocationHandler handler = new SelfInvocationHandler();
              handler.setObject(obj);
      
              return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                      obj.getClass().getInterfaces(), handler);
          }
      }
      
      public class TestAOP {
          public static void main(String[] args) {
              SuperMan man = new SuperMan();
              Object obj = MyProxy.getProxyInstance(man);
              Human sm = (Human) obj;
              sm.info();
              System.out.println();
              sm.fly();
          }
      }
      
      

    相关文章

      网友评论

          本文标题:JavaSE学习笔记——反射

          本文链接:https://www.haomeiwen.com/subject/snzplhtx.html