反射

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


图片.png

反射的功能
反射_第1张图片
图片.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 clazz1 = Person.class;
        System.out.println(clazz1);

        //方式二:通过运行时类的对象,调用getClass()(掌握)
        Person p = new Person();
        Class 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);
    }
}
反射_第2张图片
可以有Class对象的类型

举例:
反射_第3张图片
Class对象的类型

反射_第4张图片
类的加载过程
反射_第5张图片
解释类的加载过程
反射_第6张图片
类的加载过程举例

读取配置文件:

 @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 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
反射_第7张图片
图片.png

你可能感兴趣的:(反射)