Java:动态代理与反射

一、类的加载

1.1类的加载过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KsU0EnAU-1610806508512)(C:\Users\24582\AppData\Roaming\Typora\typora-user-images\image-20210106213109276.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-re5OL81p-1610806508514)(C:\Users\24582\AppData\Roaming\Typora\typora-user-images\image-20210106213248173.png)]

1.2类的加载器

在这里插入图片描述

二、反射

2.1反射的定义

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

2.2获取Class对象

/**
 * 反射:通过.class文件对象,去使用该文件中的成员变量、成员属性、成员方法
 */

public class demo1 {
    
    
    public static void main(String[] args) throws ClassNotFoundException {
    
    
        //获取Class对象
        //方式1:Object类中的getclass
        Student student = new Student("张三",18);
        Class c1 = student.getClass();
        //方式2:任意数据类型的静态class-----练习中使用
        Class c2 = Student.class;

        Student student2 = new Student("张三",18);
        Class c3 = student2.getClass();

//        System.out.println(c1==c2);//true
//        System.out.println(student==student2);//false
//        System.out.println(c1==c3);//true

        //方式3:通过Class类中的静态方法,必须指定路径----------开发中常使用
        Class c4 = Class.forName("org.wdit.Reflect.Student");
        System.out.println(c1==c4);//true
    }
}

2.3获取构造方法

/**
 * 构造方法获取
 */

public class demo2 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Class c1 = Student.class;
        //获取所有公共修饰的方法
        Constructor[] constructors = c1.getConstructors();
        for (Constructor con : constructors) {
    
    
            System.out.println(con);
        }
        System.out.println("-------------------------------------------");
        //获取所有的构造方法
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor con : declaredConstructors) {
    
    
            System.out.println(con);
        }
        System.out.println("---------------------------------------------");
        //获取一个公共的构造方法
        Constructor constructor = c1.getConstructor();
        System.out.println("------------------------------------------");
        //创建一个类对象的实例
        Object object = constructor.newInstance();
        System.out.println(object);

        System.out.println("-------------------------------------------");

        Constructor constructor1 = c1.getConstructor(String.class, int.class, String.class);
        Object o = constructor1.newInstance("李四",18,"男");
        System.out.println(o);
    }
}

2.4获取私有方法的构造

/**
 * 通过私有方法创建对象
 */
public class demo3 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Class c = Class.forName("org.wdit.Reflect.Student");
        //获取构造方法
        Constructor constructor = c.getDeclaredConstructor(String.class);
        constructor.setAccessible(true);
        Object o = constructor.newInstance("lily");
        System.out.println(o);
    }
}

2.5获取成员变量

/**
 * 获取成员变量:
 */
public class demo4 {
    
    
    public static void main(String[] args) throws Exception{
    
    
        Class c = Student.class;
        //获取所有公共的成员变量
        Field[] fields = c.getFields();
        for (Field f:fields){
    
    
            System.out.println(f);
        }
        System.out.println("-----------------------------");
        //获取所有成员变量
        Field[] declaredFields = c.getDeclaredFields();
        for (Field f:declaredFields) {
    
    
            System.out.println(f);
        }
        System.out.println("------------------------------");

        Constructor constructor = c.getConstructor();
        Object obj = constructor.newInstance();
        System.out.println(obj);
        //获取单个成员变量
        Field sex = c.getField("sex");
        Field name = c.getDeclaredField("name");
        Field age = c.getDeclaredField("age");
        sex.set(obj,"男");
        name.setAccessible(true);
        name.set(obj,"张三");
        age.set(obj,18);
        System.out.println(obj);
    }
}

//建议日后使用中,无论什么修饰权限的,我们都使用带Declared,以及设置Accessible

2.6成员方法

/**
 * 成员方法:
 */
public class demo5 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Class c = Class.forName("org.wdit.Reflect.Student");
        //获取全部成员方法 自己以及父类
        Method[] methods = c.getMethods();
        for (Method m:methods) {
    
    
            System.out.println(m);
        }
        System.out.println("---------------------------------------------");
        //获取自己的成员方法
        Method[] declaredMethods = c.getDeclaredMethods();
        for (Method m:declaredMethods) {
    
    
            System.out.println(m);
        }
        System.out.println("-------------------------------------------");
        //获取单个成员方法并使用
        Constructor constructor = c.getConstructor();
        Object o = constructor.newInstance();
        Method method = c.getMethod("show1");
        //o.show1(); 写法错误
        method.invoke(o);
        System.out.println("---------------------------------------------");
        Method method2 = c.getMethod("show2", String.class);
        method2.invoke(o,"李四");
        System.out.println("--------------------------------------------");
        Method method3 = c.getMethod("show3", String.class);
        Object o1 = method3.invoke(o, "哈哈");
        System.out.println(o1);
        System.out.println("---------------------------------------------");
        Method method4 = c.getDeclaredMethod("show4");
        method4.setAccessible(true);
        method4.invoke(o);
    }
}

2.7练习题

1:
/**
 * 使用配置文件运行类中的方法
 */
public class Testdemo {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //加载配置文件
        Properties properties = new Properties();
        FileReader fr = new FileReader("D:\\桌面\\java\\src\\Properties.txt");
        properties.load(fr);
        fr.close();
        //获取数据
        String ClassName = properties.getProperty("ClassName");
        String MethodName = properties.getProperty("MethodName");

        // 反射加载对应的类并调用方法
        Class c = Class.forName(ClassName);
        //创建对象
        Constructor constructor = c.getConstructor();
        Object o = constructor.newInstance();
        //调用方法
        Method method = c.getMethod(MethodName);
        method.invoke(o);
    }
}
2:
/**
 * 给定一个指定的泛型Integer类型的ArrayList的集合,在这个集合中添加一个字符串
 */

public class Testdemo2 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        ArrayList<Integer> arrayList = new ArrayList<>();
        //获取对应的字节码文件
        Class c = arrayList.getClass();
        //获取方法
        Method method = c.getMethod("add", Object.class);
        //使用方法
        method.setAccessible(true);
        method.invoke(arrayList,"hello");
        System.out.println(arrayList);
    }
}
3:

写一个方法,此方法可以给 指定对象的属性赋值

public class Testdemo3 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Dog dog =new Dog();
        System.out.println(dog);
        Tool tool = new Tool();
        tool.setProperty(dog,"name","博美");
        tool.setProperty(dog,"age",10);
        System.out.println(dog);
    }
}
------------------------------------------------------
class Dog{
    
    
    private String name;
    int age;

    @Override
    public String toString() {
    
    
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
------------------------------------------------------
class Tool{
    
    
    public void setProperty(Object obj,String filedName,Object value) throws Exception {
    
    
        //先拿到指定对象的字节码文件
        Class c= obj.getClass();
        //获取属性名
        Field field = c.getDeclaredField(filedName);
        //抑制访问权限
        field.setAccessible(true);
        field.set(obj,value);
    }
}

三、动态代理

3.1概述:

代理就是原本自己做的事情,请了别人帮你完成,被请的人就是代理对象

即是在程序运行过程中产生的对象-----通过反射产生代理

3.2动态代理应用

/*
 * Proxy:提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
 * public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
 *                      返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
 *
 * InvocationHandler:由代理实例的调用处理程序实现的接口。
 * invoke(Object proxy, 方法 method, Object[] args) 处理代理实例上的方法调用并返回结果。
 */
public class ProxyDemo {
    
    
    public static void main(String[] args) {
    
    
        UserDao userDao = new UserDaoImpl();
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userDao);
        //创建代理对象
        UserDao proxy = (UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),
                myInvocationHandler);
        proxy.add();
        proxy.del();
    }
}

public class MyInvocationHandler implements InvocationHandler {
    
    
    private Object object;

    public MyInvocationHandler(Object object){
    
    
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        System.out.println("权限校验");
        Object result =  method.invoke(object,args);//代理对象
        System.out.println("日志记录");
        return result;
    }
}

public interface UserDao {
    
    
    public abstract void add();
    public abstract void del();
}

public class UserDaoImpl implements UserDao {
    
    

    @Override
    public void add() {
    
    
        System.out.println("添加");
    }

    @Override
    public void del() {
    
    
        System.out.println("删除");
    }
}
ic abstract void del();
}

public class UserDaoImpl implements UserDao {
    
    

    @Override
    public void add() {
    
    
        System.out.println("添加");
    }

    @Override
    public void del() {
    
    
        System.out.println("删除");
    }
}

猜你喜欢

转载自blog.csdn.net/zjdzka/article/details/112725955