JavaSE学习笔记——反射

  • 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学习笔记——反射)