反射とは何ですか?

まず、反射の定義

ベースJDK8、Oracleの公式サイト反射の説明のために

リフレクションは、ロードされたクラスのフィールド、メソッドおよびコンストラクタに関する情報を検出するためのJavaコードを可能にし、セキュリティ上の制限の範囲内で、その基礎となる対応部分を操作することフィールド、メソッド、およびコンストラクタを使用します。APIは、(実行時のクラスに基づく)ターゲットオブジェクトのパブリックメンバーまたはメンバーのいずれかへの必要性へのアクセスが与えられたクラスが宣言したことをアプリケーションに対応します。また、抑止デフォルト反射のアクセス制御にプログラムすることができます。

既にロードされたクラス、メソッド、コンストラクタ、およびこれらのフィールドのフィールドに関する情報を発見するためのJavaコードに反射、安全限界内の反射を使用して動作するための方法およびコンストラクタ。

要するに、それはJavaランタイムを指し、

  • 所与のクラス(クラス)のオブジェクトによって反射クラス(クラス)の全ての構造部材を得るオブジェクト。
  • 特定のオブジェクトを指定し、動的で任意の属性値の取得および割り当てのそのメソッドを呼び出すことが可能です。

コンテンツのクラス、オブジェクトを作成するだけでなく、動的な呼び出し反射のために、オブジェクトのメソッドとアクションプロパティのメカニズムにこの動的なアクセス。オブジェクトの型がコンパイル時に知られていない場合でも、クラスの.classファイルが直接反射によってオブジェクトを作成することができ、存在しません。

優位

  • 死への書き込みプログラムコードの固有のロジックを回避するために、プログラムの柔軟性を高めます
  • 読み取り可能なコードのシンプルは、コードの再利用率を高めることができます

恵まれません

  • ダイレクトコールに比べ、減少が大きなシーンのパフォーマンスに反映しました
  • いくつかの内部被ばくとセキュリティリスクがあります。

第二に、リフレクションの使用

反射源のjava.lang.Classクラスは、JDKクラス統一記述と構築された私たちのカスタムクラス、実行時にクラスに格納されている情報のクラスクラス型です。Classクラスでは、図に示すような公開情報を取得することができます。連絡先Classクラスと反射が密接に関連して、クラスは、クラスを持つjava.lang.reflectと反射のためのサポートを提供します。

ここに画像を挿入説明
少年と親として、二つのクラスの人、人少年を定義し、クラスの使用法を反映参加したデモなど。

Person.class

public class Person {

    public String name;

    private int age;

    public void talk() {
        System.out.println(name + "is talking");
    }
}
复制代码

Boy.class

public class Boy extends Person {
	
    public int height;

    private int weight;

    public static String description;

    public Boy() {}

    private Boy(int height) {
        this.height = height;
    }

    public Boy(int height, int weight) {
        this.height = height;
        this.weight = weight;
    }

    public static void playBasketball() {
        System.out.println("play basketball!");
    }

    public static void playBall(String ballType) {
        System.out.println("play " + ballType + "!");
    }

    private void pickUpGirl() {
        System.out.println("pick up girl!");
    }

    public int getWeight() {
        return weight;
    }

    public int getHeight() {
        return height;
    }
}
复制代码

2.1取得クラス・オブジェクト・インスタンスの4つの方法

Class<Boy> clazz = Boy.class; // 通过类的 class 属性
Class<?> clazz2 = new Boy().getClass(); // 通过运行时类对象的 getClass 方法获取
Class<?> clazz3 = Class.forName("com.hncboy.corejava.reflection.Boy"); // 通过类的全限定名获取
Class<?> clazz4 = Main.class.getClassLoader().loadClass("com.hncboy.corejava.reflection.Boy"); // 通过类加载器获取 
复制代码

基本情報取得反映クラス2.2

クラスの基本的な情報は、情報変更が含まれている次のように、キーワードクラス、クラス名、親クラス、インタフェースは、一般的に使用される方法は次のとおりです。

int modifier = clazz.getModifiers(); // 获取类的修饰符
Package pack = clazz.getPackage(); // 获取类的包名
String fullClassName = clazz.getName(); // 获取类的全路径名称
String simpleClassName = clazz.getSimpleName(); // 获取类的简单名称
ClassLoader classLoader = clazz.getClassLoader(); // 获取类的类加载器
Class<?>[] interfacesClasses = clazz.getInterfaces(); // 获取类实现的接口列表
Class<?> superClass = clazz.getSuperclass(); // 获取类的父类
Annotation[] annotations = clazz.getAnnotations(); // 获取类的注解列表
复制代码

テストクラスを介して、上記の試験方法:

public class Test {

    public static void main(String[] args) {
        Class<Boy> clazz = Boy.class;

        // 获取类的修饰符,如果有多个修饰符,取相加后的结果
        int modifiers = clazz.getModifiers();
        System.out.println("modifiers: " + modifiers);
        System.out.println("modifiers toString: " + Modifier.toString(modifiers));

        // 获取类的包名
        Package pack = clazz.getPackage();
        System.out.println("package: " + pack);

        // 获取类的全路径名称:包名 + 类名
        String fullClassName = clazz.getName();
        System.out.println("fullClassName: " + fullClassName);

        // 获取类的简单名称:只有类名
        String simpleClassName = clazz.getSimpleName();
        System.out.println("simpleClassName: " + simpleClassName);

        // 获取类的类加载器
        ClassLoader classLoader = clazz.getClassLoader();
        System.out.println("classLoader: " + classLoader);

        // 获取类实现的接口列表
        Class<?>[] interfacesClasses = clazz.getInterfaces();
        System.out.println("interfacesClasses: " + Arrays.toString(interfacesClasses));

        // 获取类的父类
        Class<?> superClass = clazz.getSuperclass();
        System.out.println("superClass: " + superClass);

        // 获取类的注解列表
        Annotation[] annotations = clazz.getAnnotations();
        System.out.println("annotations: " + Arrays.toString(annotations));
    }
}
复制代码

次のように出力動作は次のようになります。

modifiers: 1
modifiers toString: public
package: package com.hncboy.corejava.reflection
fullClassName: com.hncboy.corejava.reflection.Boy
simpleClassName: Boy
classLoader: sun.misc.Launcher$AppClassLoader@18b4aac2
interfacesClasses: []
superClass: class com.hncboy.corejava.reflection.Person
annotations: []
复制代码

どのgetModifiersは、Java言語修飾子のような整数の符号化またはインタフェースを返します。チェックすることによりjava.lang.reflect.Modifierの APIは、すべてのバイナリ操作の修飾子値はビット演算の結果は、最速の修飾子によって決定されている、結果は型で戻り、発見しました。

ここに画像を挿入説明

フィールド2.2のリフレクション操作

フィールド情報は、クラスフィールドに格納され、フィールドは、クラスまたはインタフェース単一フィールドの、及びそれらへの動的アクセスに関する情報を提供し、および修正は可変とすることができます。反射フィールドは、クラス(静的)インスタンスフィールドまたはフィールドであってもよいです。次のように一般的な方法は以下のとおりです。

Field[] fields = clazz.getFields(); // 获取类中所有的公有字段
Field[] declaredFields = clazz.getDeclaredFields(); // 获取类中定义的字段
Field nameField = clazz.getField("name"); // 获取指定名称的公有字段
Field declaredField = clazz.getDeclaredField("likeDesc"); // 获取指定名称类中定义的字段
int modifiersField = likeDescField.getModifiers(); // 获取字段的修饰
nameField.setAccessible(true); // 指定字段强制访问
nameField.set(person, "hncboy"); // 成员字段赋值(需指定对象)
descriptionField.set(null, "hncboy"); // 静态字段赋值
复制代码

テストクラスを介して、上記の試験方法:

public class Test {

    public static void main(String[] args) throws Exception {
        Class<Boy> clazz = Boy.class;

        // 获取类中所有的公有字段,包含继承的
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        // 获取指定名称的公有字段,包含继承的
        Field nameField = clazz.getField("name");
        System.out.println(nameField);

        // 获取本类中定义的所有字段,不包含继承的,包含私有的
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field);
        }

        // 获取本类中指定名称类中定义的字段
        Field weightField = clazz.getDeclaredField("weight");
        System.out.println(weightField.getModifiers());

        // 给指定字段赋值(需指定对象)
        Boy boy = clazz.newInstance();
        // 将该字段设置为强制访问
        weightField.setAccessible(true);
        weightField.set(boy, 120);
        System.out.println(boy.getWeight());

        // 静态字段赋值,静态字段不需要指定对象
        Field descField = clazz.getField("description");
        descField.set(null, "静态属性");
        System.out.println(Boy.description);
    }
}
复制代码

次のように出力動作は次のようになります。

public int com.hncboy.corejava.reflection.Boy.height
public static java.lang.String com.hncboy.corejava.reflection.Boy.description
public java.lang.String com.hncboy.corejava.reflection.Person.name
public java.lang.String com.hncboy.corejava.reflection.Person.name
public int com.hncboy.corejava.reflection.Boy.height
private int com.hncboy.corejava.reflection.Boy.weight
public static java.lang.String com.hncboy.corejava.reflection.Boy.description
2
120
静态属性
复制代码

プライベート変数の重みに直接プライベートアクセスでは、エラーがボーイクラスのプライベート変数にアクセスすることができないとして報告されます。フィールドはjava.lang.reflect.AccessibleObjectクラスsetAccessible(boolean型のフラグ)、ネイティブsetAccessible0メソッドを呼び出すことにより、パーミッションをチェックするJava言語のアクセスをキャンセルするsetAccessible途中継承権限をオンにすることができます。

Exception in thread "main" java.lang.IllegalAccessException: Class com.hncboy.corejava.reflection.Test can not access a member of class com.hncboy.corejava.reflection.Boy with modifiers "private"
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
	at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
	at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
	at java.lang.reflect.Field.set(Field.java:761)
	at com.hncboy.corejava.reflection.Test.main(Test.java:41)
复制代码

方法の2.3反射動作

クラスメソッドでメソッドを格納する情報は、メソッドの方法は、単一のインターフェースまたはクラスの提供情報、及び単一の方法アクセスします。メソッドは、クラスまたはインスタンスメソッド(抽象含む方法)の反射であってもよいです。次のように一般的な方法は以下のとおりです。

Method[] methods = clazz.getMethods(); // 获取类中所有的公有方法
Method[] declaredMethods = clazz.getDeclaredMethods(); // 获取本类的所有方法
Method talkMethod = clazz.getMethod("talk", String.class); // 获取类中指定名称和参数的公有方法
Method pugMethod = clazz.getDeclaredMethod("pickUpGirls"); // 获取本类中定义的指定名称和参数的方法
int modifiers = pugMethod.getModifiers(); // 获取方法的修饰符
talkMethod.invoke(boy, "I tell you"); // 指定对象进行成员方法的调用
pugMethod.setAccessible(true); // 指定方法的强制访问
pickUpGirlsMethod.invoke(null); // 指定静态方法的调用
复制代码

テストクラスを介して、上記の試験方法:

public class Test {

    public static void main(String[] args) throws Exception {
        Class<Boy> clazz = Boy.class;

        // 获取类中定义的方法,包含继承的(Object)
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        // 获取类中指定的方法(无参)
        Method talkMethod = clazz.getMethod("talk");
        System.out.println(talkMethod.getName());
        
        // 获取类中指定的方法(有参)
        Method playMethod = clazz.getMethod("playBall", String.class);
        System.out.println(playMethod.getName());

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

        // 获取本类中特定的的方法
        Method declaredMethod = clazz.getDeclaredMethod("pickUpGirl");
        System.out.println(declaredMethod.getName());

        // 底层是基于构造器的创建无参构造器
        Boy boy = clazz.newInstance();
        // 调用公有有参方法
        playMethod.invoke(boy, "足球");
        // 调用私有无参方法,需要设置强制访问
        declaredMethod.setAccessible(true);
        declaredMethod.invoke(boy);

        // 调用静态方法
        Method playBasketBallMethod = clazz.getDeclaredMethod("playBasketball");
        playBasketBallMethod.invoke(null);
    }
}
复制代码

次のように出力動作は次のようになります。

public static void com.hncboy.corejava.reflection.Boy.playBasketball()
public int com.hncboy.corejava.reflection.Boy.getWeight()
public int com.hncboy.corejava.reflection.Boy.getHeight()
public static void com.hncboy.corejava.reflection.Boy.playBall(java.lang.String)
public void com.hncboy.corejava.reflection.Person.talk()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
talk
playBall
private void com.hncboy.corejava.reflection.Boy.pickUpGirl()
public static void com.hncboy.corejava.reflection.Boy.playBasketball()
public int com.hncboy.corejava.reflection.Boy.getWeight()
public int com.hncboy.corejava.reflection.Boy.getHeight()
public static void com.hncboy.corejava.reflection.Boy.playBall(java.lang.String)
pickUpGirl
play 足球!
pick up girl!
play basketball!
复制代码

getMethodsを介して利用可能なすべての親クラスのpublicメソッドでは、少年の親クラスはPersonクラスとオブジェクトクラスが含まれているので、14個のパブリックメソッドの出力の合計。getMethod取得方法または方法はパラメータをgetDeclaredMethodない場合、パラメータは、直接メソッド名に、省略することができ、取得方法のパラメータをメソッド名を指定したタイプのないNoSuchMethodException例外場合、図に示すように、エラーが報告されます。インスタンスメソッドに渡されたオブジェクトインスタンスのメソッドを呼び出す呼び出し方法によって、あなたはNULLを渡す静的メソッドを呼び出すことができます。

Exception in thread "main" java.lang.NoSuchMethodException: com.hncboy.corejava.reflection.Boy.playBall(int)
	at java.lang.Class.getMethod(Class.java:1786)
	at com.hncboy.corejava.reflection.Test.main(Test.java:29)
复制代码

コンストラクタの2.4反射操作

コンストラクタクラスコンストラクタ、コンストラクタに格納されている情報は、個々のクラスのコンストラクタ、およびクラスへのアクセスに関する情報を提供します。次のように一般的な方法は以下のとおりです。

Constructor<?>[] constructors = clazz.getConstructors(); // 获取类中所有的公有构造器
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors(); // 获取类中所有的构造器
Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(); // 获取类中无参的构造器
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, String.class); // 获取类中有参构造器
int modifiers = constructor.getModifiers(); // 获取构造器的修饰符
declaredConstructor.newInstance(); // 构造器实例对象
declaredConstructor.setAccessible(true); // 指定构造器的强制访问
constructor.newInstance("hncboy"); // 有参构造调用
clazz.newInstance(); // 直接调用默认无参构造
复制代码

テストクラスを介して、上記の試験方法:

public class Test {

    public static void main(String[] args) throws Exception {
        Class<Boy> clazz = Boy.class;

        // 获取类中所有的公有构造器
        Constructor<?>[] constructors = clazz.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }

        // 获取类中所有的构造器,包含私有的
        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor<?> constructor : declaredConstructors) {
            System.out.println(constructor);
        }

        // 获取类中无参的构造器
        Constructor<?> noParamsConstructor = clazz.getDeclaredConstructor();
        System.out.println(noParamsConstructor);

        // 获取类中指定参数构造器
        Constructor<?> constructor1 = clazz.getDeclaredConstructor(int.class);
        Constructor<?> constructor2 = clazz.getDeclaredConstructor(int.class, int.class);
        System.out.println(noParamsConstructor.getModifiers());
        System.out.println(constructor1.getModifiers());
        System.out.println(constructor2.getModifiers());

        // 调用构造器
        Boy boy = (Boy) noParamsConstructor.newInstance();
        System.out.println(boy);
        constructor1.setAccessible(true);
        boy = (Boy) constructor1.newInstance(177);
        System.out.println(boy.getHeight());
    }
}
复制代码

次のように出力動作は次のようになります。

public com.hncboy.corejava.reflection.Boy(int,int)
public com.hncboy.corejava.reflection.Boy()
public com.hncboy.corejava.reflection.Boy(int,int)
private com.hncboy.corejava.reflection.Boy(int)
public com.hncboy.corejava.reflection.Boy()
public com.hncboy.corejava.reflection.Boy()
1
2
1
com.hncboy.corejava.reflection.Boy@4b67cf4d
177
复制代码

クラスのコンストラクタは継承できませんgetConstructorsを取得するためにすべてのパブリックコンストラクタメソッドは、すべてこのクラスを取得することができます。getDeclaredConstructorsはプライベートあって、このクラスのコンストラクタのすべてを取得しました。特定のコンストラクタ引数を取得する際コンパイルプロセスにおける自動アンパックは、動作中に反映されるので、パラメータは、コンストラクタとInteger.class int.classをのように書くことができない、などに渡されます。

反射することによって、オブジェクトの2つの方法Class.newInstance()またはConstructor.newInstance()で作成することができます。ClassクラスのnewInstance下が弱い型指定された、唯一の引数なしでコンストラクタを呼び出す、無デフォルトコンストラクタあれば、ソースから見た例外のないInstantiationException例を、スロー、プロセスの性質は、リターンtmpConstructor.newInstance((オブジェクトです[ 】)NULL);,また、コンストラクタのnewInstanceメソッドを呼び出します。クラス下のコンストラクタのnewInstanceは、コンストラクタのパラメータのいずれかを呼び出すことができます。

第三に、シングルトンのための損傷

シングルトン

  • 民営化コンストラクタ
  • グローバルに一意の公衆アクセスポイント
  • 外部提供する静的メソッドのインスタンスを取得します

3.1定義式空腹空腹の男

public class Hungry {

    private static final Hungry INSTANCE = new Hungry();

    private Hungry() {}

    public static Hungry getInstance() {
        return INSTANCE;
    }
}
复制代码

怠惰な人間レイジーの3.2定義

public class Lazy {

    private static Lazy instance;

    private Lazy() {}

    public static Lazy getInstance() {
        if (instance == null) {
            synchronized (Lazy.class) {
                if (instance == null) {
                    instance = new Lazy();
                }
            }
        }
        return instance;
    }
}
复制代码

3.3定義SingletonDestroyer

public class SingletonDestroyer {

    public static void main(String[] args) throws Exception {
        // 破坏懒汉模式
        Lazy lazyInstance = Lazy.getInstance();
        Constructor<Lazy> lazyConstructor = Lazy.class.getDeclaredConstructor();
        lazyConstructor.setAccessible(true);
        Lazy lazyInstanceReflect = lazyConstructor.newInstance();
        System.out.println(lazyInstance);
        System.out.println(lazyInstanceReflect);

        // 破坏饿汉模式
        Hungry hungryInstance = Hungry.getInstance();
        Constructor<Hungry> hungryConstructor = Hungry.class.getDeclaredConstructor();
        hungryConstructor.setAccessible(true);
        Hungry hungryInstanceReflect = hungryConstructor.newInstance();
        System.out.println(hungryInstance);
        System.out.println(hungryInstanceReflect);
    }
}
复制代码

結果は、以下のように、コンストラクタは、アクセスを強制的にオブジェクトの民営化を作成し、単環式、反射モードの実施形態を破壊することが可能です。

com.hncboy.corejava.reflection.Lazy@4b67cf4d
com.hncboy.corejava.reflection.Lazy@7ea987ac
com.hncboy.corejava.reflection.Hungry@12a3a380
com.hncboy.corejava.reflection.Hungry@29453f44
复制代码

第四に、反射シンプルな春IOC Beanインスタンスの作成

IOC(制御の反転)制御の反転、彼は1つの設計のアイデアではなく、実際の技術の制御で、核となるアイデアは、プログラム(IOCコンテナ)のインスタンスを作成するために事前に設計されたオブジェクトです。地図は、基本的にコンテナKV IOCの構成です。原理は工場出荷時のパターンに加えてIOCの反映です。

春の Beanインスタンス文書に道を作成するには、3つの方法を確認してください。

  • インスタンス化を設定することにより、コンストラクタでインスタンス化
  • インスタンス化することによってインスタンスファクトリメソッドstaticファクトリを使用したインスタンス化
  • インスタンス化することによってインスタンスのファクトリメソッドの例の植物を使用したインスタンス化

次のステップ:

4.1三つのクラスA、B、Cを追加

public class A {

    public A() {
        System.out.println("调用 A 的无参构造器");
    }

    public static B createBInstance() {
        System.out.println("调用 A 的静态方法 createBInstance");
        return new B();
    }

    public C createCInstance() {
        System.out.println("调用 A 的实例方法 createCInstance");
        return new C();
    }
}

class B {}
class C {}
复制代码

4.2追加のスプリングioc.xml

プロファイルをシミュレートすることにより、オブジェクトを作成するには

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 创建方式1:无参构造器创建 A 对象-->
    <bean id="a" class="com.hncboy.corejava.reflection.A"/>

    <!-- 创建方式2:静态工厂创建,调用 A 的 createBObj 方法来创建名为 b 的对象放入容器 -->
    <bean id="b" class="com.hncboy.corejava.reflection.A" factory-method="createBInstance"/>

    <!-- 创建方式3:实例工厂创建,调用实例 a 的 createBObj 方法来创建名为 c 的对象放入容器 -->
    <bean id="c" factory-bean="a" factory-method="createCInstance"/>

</beans>
复制代码

4.3 BeanConfigを追加します。

/**
 * 存放 bean 的基本信息
 */
public class BeanConfig {

    private String id;
    private String clazz;
    private String factoryMethod;
    private String factoryBean;
    
	/* getter、setter 省略 */
}
复制代码

4.4 IOCContainerを追加します。

/**
 * 定义 map 存放 map
 */
public class IOCContainer {

    private static Map<String, Object> container = new HashMap<>();

    public static void putBean(String id, Object object) {
        container.put(id, object);
    }

    public static Object getBean(String id) {
        return container.get(id);
    }
}
复制代码

4.5追加の初期化

引数なしのコンストラクタを作成:1を作成する方法。コンテンツは、Bean IDとclazzを含みます

方法2作成:staticファクトリを作成します。ビーンIDとファクトリメソッドを含みます

3を作成する方法:インスタンスファクトリを作成します。ビーンID、工場豆工場法を含みます

public class Init {

    public static void main(String[] args) throws Exception {
        List<BeanConfig> beanConfigs = parseXmlToBeanConfig();
        // 将解析的 BeanConfig 进行实例化
        for (BeanConfig beanConfig : beanConfigs) {
            if (beanConfig.getClazz() != null) {
                Class<?> clazz = Class.forName(beanConfig.getClazz());
                if (beanConfig.getFactoryMethod() != null) {
                    // 创建方式2:静态工厂创建
                    Method method = clazz.getDeclaredMethod(beanConfig.getFactoryMethod());
                    IOCContainer.putBean(beanConfig.getId(), method.invoke(null));
                } else {
                    // 创建方式1:无参构造器创建
                    IOCContainer.putBean(beanConfig.getId(), clazz.newInstance());
                }
            } else if (beanConfig.getId() != null) {
                // 创建方式3:实例工厂创建
                Object object = IOCContainer.getBean(beanConfig.getFactoryBean());
                Method method = object.getClass().getDeclaredMethod(beanConfig.getFactoryMethod());
                IOCContainer.putBean(beanConfig.getId(), method.invoke(object));
            } else {
                System.out.println("缺少配置,无法创建对象!");
            }
        }
    }

    /**
     * 模拟解析 XML 中的 bean
     *
     * @return
     */
    private static List<BeanConfig> parseXmlToBeanConfig() {
        List<BeanConfig> beanConfigs = new ArrayList<>();
        // 模拟无参构造器创建对象
        BeanConfig beanConfig1 = new BeanConfig();
        beanConfig1.setId("a");
        beanConfig1.setClazz("com.hncboy.corejava.reflection.A");
        beanConfigs.add(beanConfig1);

        // 模拟静态工厂创建对象
        BeanConfig beanConfig2 = new BeanConfig();
        beanConfig2.setId("b");
        beanConfig2.setClazz("com.hncboy.corejava.reflection.A");
        beanConfig2.setFactoryMethod("createBInstance");
        beanConfigs.add(beanConfig2);

        // 模拟实例工厂创建对象
        BeanConfig beanConfig3 = new BeanConfig();
        beanConfig3.setId("c");
        beanConfig3.setFactoryBean("a");
        beanConfig3.setFactoryMethod("createCInstance");
        beanConfigs.add(beanConfig3);

        return beanConfigs;
    }
}
复制代码

結果は以下の通りであります:

调用 A 的无参构造器
调用 A 的静态方法 createBInstance
调用 A 的实例方法 createCInstance
复制代码

Javaリフレクション完全に解決

InsightsのJavaリフレクション

公衆との同期資料番号Githubには、その後、あなたは作者に連絡することができます問題があります。

ブリリアントライフ
マイクロチャネルの2次元コードスキャン、社会的関心私の電話番号

おすすめ

転載: juejin.im/post/5def3289f265da33b82be8fb