Java:動的プロキシとリフレクション

1つ、クラスの読み込み

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.2Classオブジェクトを取得する

/**
 * 反射:通过.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つのダイナミックなエージェンシー

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