Java に基づくリフレクションおよび動的プロキシの知識ポイントの概要

反射

リフレクションの概要

リフレクションにより、メンバー変数、メンバー メソッド、およびコンストラクターに関する情報にプログラムからアクセスできます。

次の図を使用すると、この概念がより明確になる場合があります。リフレクションはクラスから物事を取得できます

ここに画像の説明を挿入

リフレクションの用途は何ですか?
実はアイデアのメソッド表示はリフレクションを使っているのですが、メソッドのパラメータを書くとき、パラメータの型がはっきりしないので、 Ctrl + P で表示されているパラメータの型がわかります。
ここに画像の説明を挿入


リフレクションはクラス内のすべての詳細情報を取得でき、きれいです. 詳細は下の図で見ることができ、リフレクションを通じて次の内容を取得できます.

ここに画像の説明を挿入


反射取得

リフレクションはクラス オブジェクトを取得します

クラス バイトコード ファイル オブジェクトを取得した後でのみ、メンバ変数とその中の他のコンテンツを取得できます。

ここに画像の説明を挿入


クラス オブジェクトを取得する 3 つの方法

①class.forName("完全なクラス名");
②クラス名.class
③object.getclass();

クラス オブジェクト コードを取得する 3 つの方法は次のとおりです。

    public static void main(String[] args) throws ClassNotFoundException {
    
    
        /**
         * 获取class字节码文件对象的三种方式
         * 1.Class.forName("全类名")
         * 2.类名.class
         * 3.对象.getClass()
         */
        //第一种方式
        //全类名 = 包名 + 类名
        //是最为常用的
        Class clazz1 = Class.forName("org.example.Student");
        System.out.println(clazz1);

        //第二种方式
        //类名.class  更多用于参数传递,比如多线程中的同步代码块 synchronized (类名.class)
        Class clazz2 = Student.class;
        System.out.println(clazz2);

        //第三种方式
        //对象.getClass()    当我们有了这个类的对象时,才可以使用
        Student student = new Student();
        Class clazz3 = student.getClass();
        System.out.println(clazz3);
    }

コンストラクタを取得するリフレクション

Class クラスのコンストラクター メソッドを取得するために使用されるメソッド

Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组Constructor<?>[] 	
getDeclaredConstructors():返回所有构造方法对象的数组,包括私有的方法
Constructor<T> getConstructor(Class<?>... parameterTypes):返回单个公共构造方法对象
Constructor<T>getDeclaredConstructor(Class<?>... parameterTypes):返回单个构造方法对象

注: Declared (許可) があれば誰でも private メソッドを取得できます
オブジェクトを作成するための Constructor クラスのメソッド

T newInstance(Object... initargs):根据指定的构造方法创建对象
setAccessible(boolean flag):设置为true,表示取消访问检查

以下はコードの実装です

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    
    
        Class clazz = Class.forName("org.example.Student");

        //获取所有构造方法
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
    
    
            System.out.println(constructor);
        }

        //获取指定的构造方法
        Constructor con = clazz.getDeclaredConstructor(String.class, int.class);
        //暴力反射:表示临时取消权限校验
        con.setAccessible(true);
        Object instance = con.newInstance("张三", 12);
        System.out.println(instance);
    }

メンバー変数を取得するリフレクション

Class クラスのメンバー変数を取得するために使用されるメソッド

Field[] getFields():返回所有公共成员变量对象的数组
Field[] getDeclaredFields():返回所有成员变量对象的数组
Field getField(String name):返回单个公共成员变量对象
Field getDeclaredField(String name):返回单个成员变量对象

オブジェクトを作成するための Field クラスのメソッド

void set(Object obj, Object value):赋值object get(Object obj)获取值。

コードは次のように実装されます

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
    
    
        Class clazz = Class.forName("org.example.Student");

        //获取所有变量
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
    
    
            System.out.println(field);
        }

        //获取单个变量
        Field field = clazz.getDeclaredField("name");
        System.out.println(field);

        //获取权限修饰符
        int modifiers = field.getModifiers();
        System.out.println(modifiers);

        //获取成员变量名
        String fieldName = field.getName();
        System.out.println(fieldName);

        //获取成员变量的数据类型
        Class<?> type = field.getType();
        System.out.println(type);

        //获取成员变量的值
        Student student = new Student("张三", 12);
        field.setAccessible(true);
        String value =(String)field.get(student);
        System.out.println(value);

        //修改变量里记录的值
        field.set(student,"李四");
    }

リフレクション get member メソッド

Class クラスのメンバー メソッドを取得するために使用されるメソッド

Method[ ] getMethods():返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes):返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回单个成员方法对象

Method クラスでオブジェクトを作成するために使用されるメソッド
Object invoke(Object obj, Object... args): メソッドを実行します パラメータ
1: obj オブジェクトを使用してメソッドを呼び出します
パラメータ 2: メソッドの渡されたパラメータを呼び出します (そうでない場合)
return Value: メソッドの戻り値 (書かれていない場合)


コードは次のように実装されます

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    
    
        Class clazz = Class.forName("org.example.Student");

        //获取所有的方法对象(包含父类所有的公共方法)
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
    
    
            System.out.println(method);
        }

        //获取本类中的所有私有方法,不能获取父类的
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
    
    
            System.out.println(declaredMethod);
        }

        //获取指定成员方法
        Method m = clazz.getDeclaredMethod("run", void.class);
        //获取方法修饰符和获取方法名字都和获取成员变量一样

        //获取方法的所有形参
        Parameter[] parameters = m.getParameters();
        for (Parameter parameter : parameters) {
    
    
            System.out.println(parameter);
        }

        //获取方法抛出的异常
        Class[] exceptionTypes = m.getExceptionTypes();
        for (Class exceptionType : exceptionTypes) {
    
    
            System.out.println(exceptionType);
        }

        //运行方法
        Student student = new Student("张三", 12);
        m.setAccessible(true);
        //参数一:表示方法调用者
        //参数二:表示调用方法时实际传递的参数
        m.invoke(student,"屌毛");
    }

反射解剖学

リフレクション:
① クラス内のすべての情報を取得し、取得後に他のビジネス ロジックを実行する
② 構成ファイルを組み合わせて動的にオブジェクトを作成し、メソッドを呼び出す

リフレクションを構成ファイルと組み合わせて、オブジェクトを動的に作成し、メソッドを呼び出すことができます

获得class字节码文件对象的三种方式
①Class.forName("全类名");
②类名.class
③对象.getClass();

ここに画像の説明を挿入


動的プロキシ

ダイナミックエージェンシー思考

元のメソッドの機能を強化するために、Spring の AOP は動的プロキシを使用します
ここに画像の説明を挿入
機能: コードに追加機能を追加するための非侵入型



大スターがいる典型的なケースについて話しましょう、兄は歌、ダンス、ラップの方法を持っていて、公演会場の準備と公演料の収集方法を持っているので、彼が対処するのを助けるためにマネージャーが雇われました. 、 ブラザー・ジはただ歌い、踊り、ラップしたかっただけです。これは代理店です。

対象者がやりすぎたと思った場合、エージェントを通じて責任の一部を譲渡することができます。

なぜエージェントが必要なのですか?
プロキシは、他の機能を非侵入的にオブジェクトに拡張できます
ここに画像の説明を挿入

Java がプロキシの外観を保証するものは何ですか?
インターフェイスの保証により、次のオブジェクトとプロキシは同じインターフェイスを実装する必要があり、インターフェイスにはプロキシされたオブジェクトのすべてのメソッドが含まれています。

オブジェクトに何らかのメソッドがあり、プロキシされる必要がある場合、プロキシには対応するメソッドが必要です


動的プロキシ コードの実装

プロキシ クラスとプロキシ クラスの両方が共通のインターフェイスを実装する必要があり、書き換えを実現するために拡張する必要があるメソッド
ここに画像の説明を挿入


共通インターフェースを実装する

public interface Star {
    
    

    //把想要代理的方法定义在接口中

    //唱歌
    public abstract String Sing(String songName);

    //跳舞
    public abstract void Dance();
}


エージェント クラス

public class BigStart implements Star{
    
    
    private String name;

    public BigStart() {
    
    
    }

    public BigStart(String name) {
    
    
        this.name = name;
    }

    @Override
    public String Sing(String songName){
    
    
        System.out.println(this.name + "正在唱" + songName);
        return "谢谢";
    }
    @Override
    public void Dance(){
    
    
        System.out.println(this.name + "正在跳舞");
    }
    /**
     * 获取
     * @return name
     */
    public String getName() {
    
    
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
    
    
        this.name = name;
    }

    public String toString() {
    
    
        return "BigStart{name = " + name + "}";
    }
}

プロキシ クラス

public class ProxyUtil {
    
    

    public static Star createProxy(BigStart bigStart) {
    
    

        Star star = (Star) Proxy.newProxyInstance(
                ProxyUtil.class.getClassLoader(),
                new Class[]{
    
    Star.class},

                new InvocationHandler() {
    
    
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
                        if ("Sing".equals(method.getName())) {
    
    
                            System.out.println("准备话筒,收钱");
                        } else if ("Dance".equals(method.getName())) {
    
    
                            System.out.println("准备场地,收钱");
                        }

                        return method.invoke(bigStart, args);
                    }
                }
        );
        return star;
    }
}

主な方法

public class Main {
    
    
    public static void main(String[] args) {
    
    
        //1.获取代理的对象
        BigStart bigStart = new BigStart("鸡哥");
        Star proxy = ProxyUtil.createProxy(bigStart);

        //2.调用唱歌的方法
        String result = proxy.Sing("只因你太美");
        System.out.println(result);
    }
}

おすすめ

転載: blog.csdn.net/giveupgivedown/article/details/129048537