反射

作者: vv_64ce | 来源:发表于2020-04-18 17:17 被阅读0次

    反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并直接操作任意对象的内部属性和方法


    图片.png 反射的功能 图片.png java.lang.Class类的加载理解
    1.类的加载过程:

    程序经过javac.exe命令后,会生成一个或多个字节码文件(.class结尾);接着我们使用java.exe命令对某个字节码文件进行解释运行,相当于将某个字节码文件加载到内存中,此过程称为类的加载。加载到内存中的类,称为运行时类,此时运行时类,就作为Class的一个实例
    2.换句话说,Class的实例就对应着一个运行时类
    3.加载到内存中的运行时类,会缓存一定的时间。在此时间之内,可以沟通过不同方式获取此运行时类

    获取Class的实例的方式(掌握三种)
    public class ReflectPerson {
        @Test
        public void test01() throws ClassNotFoundException {
            //方式一:调用运行时类的属性,.class(掌握)
            Class<Person> clazz1 = Person.class;
            System.out.println(clazz1);
    
            //方式二:通过运行时类的对象,调用getClass()(掌握)
            Person p = new Person();
            Class<? extends Person> clazz2 = p.getClass();
            System.out.println(clazz2);
    
            //方式三:调用Class的静态方法,forName(String classPath)((掌握)使用频率高)
            Class<?> clazz3 = Class.forName("com.vv.reflect.Person");
            System.out.println(clazz3);
    
            System.out.println(clazz1 == clazz2);
            System.out.println(clazz3 == clazz2);
    
            //方式四:使用类的加载器,ClassLoader(了解)
            ClassLoader loader = ReflectPerson.class.getClassLoader();
            Class<?> clazz4 = loader.loadClass("com.vv.reflect.Person");
            System.out.println(clazz4);
        }
    }
    
    可以有Class对象的类型 举例: Class对象的类型
    类的加载过程 解释类的加载过程 类的加载过程举例

    读取配置文件:

     @Test
        public void test01() throws IOException {
            Properties pro = new Properties();
            //读取配置文件方式一:默认当前project下
            //读取文件
            FileInputStream fis = new FileInputStream("src\\db1.properties");
            //加载文件
            pro.load(fis);
    
    //        //读取配置文件方式二:文件默认识别为当前moudle的src下
    //        InputStream is = Propeties01.class.getClassLoader().getResourceAsStream("db1.properties");
    //        pro.load(is);
    
            String name = pro.getProperty("name");
            String age = pro.getProperty("age");
            System.out.println(name+"......"+age);
        }
    

    通过反射运行时的类获得其属性、方法、构造器

    @Test
        public void field() throws Exception {
            //1.创建Class的对象
            Class<Person> clazz = Person.class;
            //2.创建该对象的实例,便于调用对象的属性、方法、构造器
            Person person = clazz.newInstance();
    
            //3.获得该属性
            Field name = clazz.getDeclaredField("name");
            //4.保证当前属性是可访问的
            name.setAccessible(true);
            //5.获取、设置指定对象的此属性值
            name.set(person,"张三");
            System.out.println(name.get(person));
        }
        @Test
        public void method() throws Exception {
            Class clazz = Person.class;
            Person p = (Person) clazz.newInstance();
            Method declaredMethod = clazz.getDeclaredMethod("showTime",int.class);
            declaredMethod.setAccessible(true);
            //调用的invoke():参数1:方法的调用者  参数2:给方法形参赋值的实参
            // invoke()的返回值即为对应勒种调用方法的返回值
            Object o = declaredMethod.invoke(p, 12);
            System.out.println(o);
    
            System.out.println("**********");
    
            //静态方法的调用,不需要在进行创建对象
            Method staticTest = clazz.getDeclaredMethod("staticTest");
            staticTest.setAccessible(true);
            //调用的invoke方法没有返回值时,参数可以为null
            staticTest.invoke(clazz);// staticTest.invoke(null);
    
        }
        @Test
        public void constructor() throws Exception {
            Class clazz = Person.class;
            Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class);
            declaredConstructor.setAccessible(true);
            Object instance = declaredConstructor.newInstance("张三", 13);
            System.out.println(instance);
        }
    
    反射的应用:动态代理
    public class ProxyTest {
    
       @Test
       public void test(){
           Man man = new Man();
           Human proxyInstance = (Human) ProxyFactory.getProxyInstance(man);
           proxyInstance.breath();
           proxyInstance.eat("苹果");
    
       }
    }
    interface Human{
       void breath();
       void eat(String food);
    }
    //被代理类
    class Man implements Human{
    
       @Override
       public void breath() {
           System.out.println("Man呼吸新鲜空气");
       }
    
       @Override
       public void eat(String food) {
           System.out.println("Man吃"+food);
       }
    }
    /*
    要想创建动态代理:
    1.如何根据加载到内存中的被代理类,动态创建一个代理类及对象
    2.当通过代理类的对象调用方法时,如何动态调用被代理类中的同名方法
    */
    class ProxyFactory{
    
       //创建动态代理,
       //解决一:调用此方法,返回一个代理类对象Object;参数Object obj是被代理类的对象
       public static Object getProxyInstance(Object obj){
           //创建Handler对象
           MyInvocatoinHandler handler = new MyInvocatoinHandler();
           handler.bind(obj);
           //参数一:被代理类的类的加载器  参数二:被代理类的接口 参数三:调用代理类中的同名方法
           return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),handler);
       }
    
    
    }
    //实现InvocationHandler接口
    class MyInvocatoinHandler implements InvocationHandler{
       private Object obj;//需要使用被代理对象进行赋值
       public void bind(Object obj){
           this.obj = obj;
       };
       //Object proxy:动态代理的对象
       //Method method:调用的反射类中的方法
       //Object[] args:method中的参数
       //Object返回值类型是method方法中的返回值类型
       @Override
       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
           //被代理类的执行方法功能声明
           return method.invoke(obj,args);
    
       }
    }
    
    动态代理和AOP
    图片.png

    相关文章

      网友评论

          本文标题:反射

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