SpringのgetBeanメソッドのソースコード分析

SpringのgetBeanメソッドのソースコード分析

TSMYK Javaテクノロジプログラミング
テキストでは、次の領域を紹介します

  1. FactoryBeanインターフェース
  2. BeanFactoryインターフェース
  3. BeanFactoryインターフェースとFactoryBeanインターフェースの違い
  4. getBeanメソッドのソースコード分析
  5. 春の循環依存ソリューション

    関連記事


SpringでのBean登録のソースコード分析
SpringBean作成プロセスソースコード分析SpringAOP関数は詳細な
SpringAOPアノテーションメソッドを使用しますソースコード分析
SpringAOP作成プロキシソースコード分析
Springトランザクションは詳細な
Springトランザクション初期化ソースコード分析を使用します
Springトランザクションのコミットとロールバックソースコード分​​析

序文

記事では、Bean登録のSpringソースコード分析とSpring Bean作成プロセスのソースコード分析は、Beanの登録と作成プロセスを理解しています。対応するBeanがgetBeanメソッドを介して取得されるとどうなりますか?

getBeanメソッドの内部実装を見てみましょう。getBeanメソッドに入る前に、FactoryBeanインターフェースを見てみましょう。このインターフェースの実装クラスは、getBeanメソッド内で個別に処理されるためです。

FactoryBean

このインターフェースはBeanFactoryインターフェースと非常に似ていますが、その機能は完全に異なります。javadocドキュメントの定義を見てみましょう。一般的な意味は次のとおりです。Beanがこのインターフェースを実装する場合、BeanがgetBeanメソッドを介して取得される場合、それ自体は返されません。代わりに、getObject()メソッドの戻り値を返します。さらに、FactoryBeansはシングルトンモードとプロトタイプモードをサポートできます。そのソースコードは次のとおりですが、3つの方法しかありません。


public interface FactoryBean<T> {
    // 返回 bean 的实例,即调用 getBean 方法获取到的实例就是该方法的返回值 
    T getObject() throws Exception;

    // 返回 bean 的类型
    Class<?> getObjectType();

    // 该 bean 是否是单例模式
    boolean isSingleton();
}

では、このFactoryBeanインターフェースの用途は何ですか?Spring Bean作成プロセスのソースコード分析により、Beanのインスタンス化はリフレクションとCGLIBを使用して実現されることがわかっていますが、場合によっては、Beanのインスタンス化プロセスがより複雑になります。従来の方法に従うと、構成ファイルで構成する必要があります<bean>多くの構成情報を提供します。構成方法の柔軟性には限界がありますが、現時点では、コーディング方法を使用することで簡単なスキームを得ることができます。したがって、ユーザーはこのインターフェースを実装することにより、Beanをインスタンス化するロジックをカスタマイズできます。

くるみ

最初に栗を見てみましょう。これでUserオブジェクトができました。従来の方法は、構成ファイルで次のように構成されています。


public class User {

    private String name;
    private int age;
    private int sex;
    private double money;
    private String job;

    // setter / getter / toString
}
<bean id="user" class="main.tsmyk.pojo.User">
    <property name="name" value="zhangsan"/>
    <property name="age" value="20"/>
    <property name="job" value="java"/>
    <property name="money" value="10000"/>
    <property name="sex" value="1"/>
</bean>

テスト:


ApplicationContext context = new ClassPathXmlApplicationContext("myspring.xml");
User user = (User) context.getBean("user");
System.out.println(user);
结果:User{name='zhangsan', age=20, sex=1, money=10000.0, job='java'}

印刷された結果から、Userオブジェクトの属性がすべて値に関連付けられていることがわかります。

ただし、Userオブジェクトに多くのプロパティがあり、多くの<property>タグを記述したくない場合は、FactoryBeanインターフェイスを介して実装できます。インターフェイス内で、Userオブジェクトのプロパティが解析されて割り当てられます。特定のルールに従って。次のように:


public class UserFactoryBean implements FactoryBean<User> {

    private String user;

    @Override
    public User getObject() throws Exception {
        User user = new User();
        String[] userInfos = this.user.split(";");
        user.setName(userInfos[0]);
        user.setAge(Integer.parseInt(userInfos[1]));
        user.setJob(userInfos[2]);
        user.setMoney(Double.parseDouble(userInfos[3]));
        user.setSex(Integer.parseInt(userInfos[4]));
        return user;
    }

    @Override
    public Class<User> getObjectType() {
        return User.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

    public String getUser() {
        return user;
    }
    public void setUser(String user) {
        this.user = user;
    }
}

このクラスのgetObjectメソッドでは、Userオブジェクトのプロパティが解析されて割り当てられます。getBeanメソッドを介してBeanを取得すると、getObjectメソッドによって返されるUserオブジェクトが取得されます。構成は次のとおりです。


<bean id="userFactory" class="main.tsmyk.beans.UserFactoryBean">
    <property name="user" value="zhangsan;20;java;10000;1"/>
</bean>

テスト:


ApplicationContext context = new ClassPathXmlApplicationContext("myspring.xml");
User user1 = (User) context.getBean("userFactory");
System.out.println(user1);
结果:User{name='zhangsan', age=20, sex=1, money=10000.0, job='java'}

上記の従来の方法と同じであることがわかります。また、getBeanメソッドがFactoryBeanインスタンス自体ではなく、getObjectメソッドの戻り値を取得することも確認されています。ただし、FactoryBeanインスタンス自体を取得する場合は、Bean名の前に&記号を追加するだけでも可能です。つまり、getBean( "&userFactory")

テスト:


ApplicationContext context = new ClassPathXmlApplicationContext("myspring.xml");
UserFactoryBean userBean = (UserFactoryBean) context.getBean("&userFactory");
System.out.println(userBean.getUser());

结果:zhangsan;20;java;10000;1

黒板をノックする:したがって、getBean(String beanName)メソッドを介してインスタンスを取得する場合、beanNameは&で始まる場合があります。beanNameが&で始まる場合は、FactoryBeanインターフェースが処理されていることを意味します。

Spring自体も、JndiObjectFactoryBeanクラスなど、FactoryBeanインターフェースの多くの実装を提供します。


public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryBean<Object>, BeanFactoryAware, BeanClassLoaderAware {
    private Object jndiObject;
    // 其他复杂的计算,为 jndiObject 赋值
    @Override
    public Object getObject() {
        return this.jndiObject;
    }
}

よく知られているサードパーティのORMフレームワークMybatisも、このインターフェイスSqlSessionFactoryBeanの実装を提供します。


<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    // 其他配置
</bean>
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
  private SqlSessionFactory sqlSessionFactory;
  @Override
  public SqlSessionFactory getObject() throws Exception {
    if (this.sqlSessionFactory == null) {
      afterPropertiesSet();
    }

    return this.sqlSessionFactory;
  }
  // 其他方法
}

したがって、getBeanメソッドを使用すると、SqlSessionFactoryBeanではなくSqlSessionFactoryが取得されます。

BeanFactory

次に、FactoryBeanに非常によく似たインターフェースBeanFactoryを見てみましょう。BeanFactoryはSpring IOCコンテナーのコアインターフェースであり、Beanの作成、Beanの取得など、コンテナーの主な機能を定義します。 Beanを管理します。つまり、アプリケーション内のオブジェクトをインスタンス化、検索、構成し、これらのオブジェクト間の依存関係を確立するために使用されます。そのソースコードは次のとおりです。


public interface BeanFactory {

    String FACTORY_BEAN_PREFIX = "&";
    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    boolean containsBean(String name);
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, ResolvableType typeToMatch);
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    String[] getAliases(String name);
}

コンテナの基本関数が定義されていることがわかります。ファクトリBeanインターフェースを表すために使用されるbeanNameのプレフィックスである属性FACTORY_BEAN_PREFIX = "&"があることに注意してください。

総括する

この時点で、ソースコードからわかるように、FactoryBeanとBeanFactoryは非常に似ていますが、それらの役割は完全に異なります
。FactoryBeanはファクトリと見なされ、それを使用していくつかの複雑なBeanを作成できます。BeanFactoryはの
基本関数を定義します。Springコンテナ。達成するサブクラス、Beanの管理に使用

getBeanメソッド

ユーザーuser =(ユーザー)beanFactory.getBean( "user");


    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

    @Override
    public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
        return doGetBean(name, requiredType, null, false);
    }

    @Override
    public Object getBean(String name, Object... args) throws BeansException {
        return doGetBean(name, null, args, false);
    }

次に、少し複雑なdoGetBeanメソッドを見てください。


protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly){
    // 提取对应的 beanName,处理别名和FactoryBean接口的实现类,即 beanName 以 & 开头
    final String beanName = transformedBeanName(name);
    Object bean;
    // 尝试从缓存中或者ObjectFactory中获取
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (isSingletonCurrentlyInCreation(beanName)) {
            logger.debug("......");
        }
        // 这里主要处理 FactoryBean,有时候并不是返回实例本身,而是返回指定方法返回的实例
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    // 缓存中不存在该bean的实例
    else {
        // 这里bean的作用域是原型模式,且存在循环依赖,出现循环依赖,则抛出异常
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // 如果当前的的beanDefinitionMap即配置文件不包含该bean,则从parentBeanFactory 中查找
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            String nameToLookup = originalBeanName(name);
            if (args != null) {
                // 这个 args 是 getBean(beanName, args...) 方法传入的
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else {
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }
        // 如果不仅仅是做类型检查,则是创建bean,则进行标记,标记该bean以创建
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }
        // 将配置文件中GenericBeanDefinition转换为RootBeanDefinition,如果beanName是子bean的话,会合并父类的属性
        final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
        checkMergedBeanDefinition(mbd, beanName, args);

        // 处理依赖,如果存在依赖,则递归实例化依赖的bean
        String[] dependsOn = mbd.getDependsOn();
        if (dependsOn != null) {
            for (String dep : dependsOn) {
                if (isDependent(beanName, dep)) {
                        throw new BeanCreationException("........");
                }
                registerDependentBean(dep, beanName);
                getBean(dep);
            }
        }
        //实例化 bean
        if (mbd.isSingleton()) {
            // 实例化单例的bean
            sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {                   
                    return createBean(beanName, mbd, args);
                });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
        else if (mbd.isPrototype()) {
            // 实例化原型的bean
            Object prototypeInstance = null;
            try {
                beforePrototypeCreation(beanName);
                prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
                afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
        }
        else {
            // 指定的 score 上实例化bean
            String scopeName = mbd.getScope();
            final Scope scope = this.scopes.get(scopeName);
            Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    beforePrototypeCreation(beanName);
                    try {
                        return createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    });
                bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
            }
        }
    }
    // 处理参数类型的转换
    if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
        return getTypeConverter().convertIfNecessary(bean, requiredType);
    }
    return (T) bean;
}

上記のコードからわかるように、doGetBeanメソッドのプロセスは非常に明確であり、各ステップは対応するメソッドを使用して処理されます。そのプロセスは主に次のとおりです。

  1. BeanNameを処理する場合、Beanはエイリアスを持つことができるため、なぜbeanNameを処理する必要がありますか。また、上記のFactoryBeanインターフェースの導入時に、Beanを取得するときに&プレフィックスを追加する必要があるため、ここで&を削除する必要があります。

  2. シングルトンBeanは1回しかロードされないため、キャッシュからBeanをロードしてみてください。Beanがキャッシュに存在しない場合は、singletonFactoriesからBeanをロードしようとします。このsingletonFactoriesとは何ですか。Spring Bean作成プロセスのソースコード分析では、Beanの作成時に依存性注入が発生する可能性があることがわかっています。依存性Beanを作成する場合、循環依存を回避するために、Beanの作成時に待機しません。 Beanの作成が​​完了するまで、Beanを作成したObjectFactoryをsingletonFactoriesキャッシュに配置します。次のBeanが作成されたら、前のBeanに依存して、singletonFactoriesキャッシュから直接ObjectFactoryを取得して作成する必要があります。

たとえば、AはBに依存し、A-> Bです。AのインスタンスbeanAを作成します。作成プロセス中に、Aによって作成されたObjectFactoryをsingletonFactoriesキャッシュに配置します。AがBに依存するようになったので、 BのインスタンスbeanB。、beanAは、beanBが作成された後も引き続き作成されます
。BもA、B-> Aに依存していることが判明した場合、beanBが作成されると、beanAも最初に作成されます。 AインスタンスbeanAの作成、AのObjectFactoryがキャッシュに配置されたので、キャッシュに移動してObjectFactoryを取り出すことができます。AのObjectFactoryを事前にキャッシュに配置していなかった場合は、想像してみてください。 Bを作成するときは、最初にAを作成します。AがBに依存していることが判明すると、Bが再度作成されます。これにより、循環依存が発生し、インスタンス化が失敗します。

したがって、Springはこのメソッドを使用してBean間の循環依存関係を解決しますが、シングルトン循環依存関係のみを処理し、プロトタイプまたはその他の例外がスローされます。

3.Beanの作成
3.1親クラスからのBeanの検索
3.2GenericBeanDefinitionをRootBeanDefinitionに変換します。これは、構成ファイルからBeanをロードするときに、GenericBeanDefinitionモードで保存されるためです。3.3
依存関係の処理
3.4シングルトンBeanの
作成3.5プロトタイプBeanの
作成3.6他のスコアの作成
3.7パラメータータイプの変換作用する豆の

4.FactoryBeanインターフェースのBeanの処理

プロセスが非常に明確であるかどうかにかかわらず、フローチャートを通じてより明確になります。
SpringのgetBeanメソッドのソースコード分析

それぞれの部分を見てみましょう。

1.beanNameを抽出します

getBeanメソッドを使用してBeanを取得する場合、Beanの名前は&で始まることができます。つまり、FactoryBeanインスタンス自体が取得されます。さらに、Beanにはエイリアスがあり、Beanには複数のエイリアスがあるなどです。 Beanの名前を最初に抽出する必要があります。、メソッドtransformedBeanName:


final String beanName = transformedBeanName(name);

protected String transformedBeanName(String name) {
    String beanName = BeanFactoryUtils.transformedBeanName(name);
    return canonicalName(beanName);
}

// 使用工具类 BeanFactoryUtils 来转名字
public static String transformedBeanName(String name) {
    String beanName = name;
    // 如果 beanName 以 & 开头,则去掉 &
    while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
    }
    // 返回去掉 & 后的 beanName
    return beanName;
}

// 返回原始的bean的名字,解决别名
public String canonicalName(String name) {
    String canonicalName = name;
    String resolvedName;
    // while 循环,因为 bean 的别名可以有多个
    do {
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    while (resolvedName != null);
    return canonicalName;
}

2.キャッシュからBeanインスタンスを取得してみます


Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
    // 处理 FactoryBean
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

// 获取 bean
public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 从缓存中获取bean,该缓存singletonObjects用来存放已经创建完毕的bean的实例
    Object singletonObject = this.singletonObjects.get(beanName);
    // 如果缓存中没有,且该 bean 正在创建
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) { 
            // 从正在创建bean的缓存中获取,该 earlySingletonObjects 缓存是用来存放正在创建且还没有创建完毕的bean
            singletonObject = this.earlySingletonObjects.get(beanName);
            // 如果此时还是获取不到实例,且允许从ObjectFactory中获取,解决循环引用
            if (singletonObject == null && allowEarlyReference) {
                // 从 ObjectFactory 中获取对应的工厂,使用工厂创建创建对象,因为之前在创建该bean的时候且还没有创建完毕的时候,已经把该bean的 ObjectFactory 放入到缓存中
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                // 获取到工厂之后,进行创建bean的实例,并放入到对应的缓存中
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    // 如果缓存中没有,且该bean没有正在创建,则直接返回 nul
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

この方法では、循環依存関係の解決を試みます。この方法には、次の3つのマップタイプのキャッシュが含まれます。

  1. キャッシュsingletonObjectsは、作成されたBeanインスタンスを格納するために使用されます
  2. キャッシュearlySingletonObjectsは、作成されているがまだ作成されていないBeanを格納するために使用されます
  3. キャッシュされたObjectFactoryは、対応するファクトリを格納するために使用されます。これは、Beanが作成される前後に、BeanのObjectFactoryがキャッシュに配置されている
    ためです。したがって、上記のメソッドの主なロジックは、最初にsingletonObjectsからインスタンスを取得することです。 、取得できない場合はBeanが作成されていません。取得できない場合は、Beanが作成されていないことを意味し、ObjectFactoryから対応するファクトリを取得して作成します。それでも取得できない場合は最後に、nullを返します

3.FactoryBeanの処理

Beanインスタンスを取得した後、FactoryBeanやfactory-methodなどのメソッドを処理する必要があります。さまざまなスコアからBeanインスタンスを取得した後、メソッドが実行されます。


protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

    // 如果 bean 的实例不是 FactoryBean 类型,即是一般的 bean ,可以直接返回
    // 如果 beanName 是以 & 开头,则也直接返回,因为 beanName 以 & 开头,表示返回工厂实例本身
    // BeanFactoryUtils.isFactoryDereference : name != null && name.startsWith("&")
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    Object object = null;
    if (mbd == null) {
        // 尝试从 FactoryBean 缓存中获取bean
        object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
        // 到这里,已经明确了 bean的实例一定是 FactoryBean 类型
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}
// 通过 FactoryBean 来获取 bean 实例
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    // 忽略了其他代码
    // doGetObjectFromFactoryBean -> factory.getObject(),返回的是 FactoryBean 的 getObject 方法的返回值
    object = doGetObjectFromFactoryBean(factory, beanName);
    return object;
}

4.Beanを作成します

上記の手順の後、キャッシュにインスタンスがない場合、Beanはインスタンス化されます。作成前に、Beanに依存Beanがある場合、依存Beanが最初に処理されます。

4.1依存Beanの処理


String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
    for (String dep : dependsOn) {
        if (isDependent(beanName, dep)) {
            throw new BeanCreationException("循环依赖异常");
        }
        // 注册循环依赖
        registerDependentBean(dep, beanName);
        // 创建依赖的 bean
        getBean(dep); // return doGetBean(name);
    }
}

4.2Beanを作成する


if (mbd.isSingleton()) {
    // 创建单例的bean
    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
        @Override
        public Object getObject() throws BeansException {
            return createBean(beanName, mbd, args);
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
    // 创建原型的bean 
    Object prototypeInstance = null;
    try {
        beforePrototypeCreation(beanName);
        prototypeInstance = createBean(beanName, mbd, args);
    }
    finally {
        afterPrototypeCreation(beanName);
    }
    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
    // 创建其他score的bean
    String scopeName = mbd.getScope();
    final Scope scope = this.scopes.get(scopeName);
    Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
        public Object getObject() throws BeansException {
        beforePrototypeCreation(beanName);
        try {
            return createBean(beanName, mbd, args);
        }
        finally {
            afterPrototypeCreation(beanName);
        });
        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}

シングルトンBeanおよび他のスコアのBeanの作成は、SpringBean作成プロセスのソースコード分析のcreateBeanメソッドを参照できます。

プロトタイプBeanを作成するプロセスを見てみましょう。


protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    RootBeanDefinition mbdToUse = mbd;
    // 解析 class 
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // 处理 lookup-method 和 replace-method 属性,在 “Spring 中 bean 注册的源码解析“ 从已经解析过
    mbdToUse.prepareMethodOverrides();
    // 在该方法里面会执行前置处理器和后置处理器
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    // 如果应用前置处理和后置处理器改变了bean,就直接返回,AOP功能就在此实现
    if (bean != null) {
        return bean;
    }
    // 正真创建bean
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    return beanInstance;
}

// 应用前置处理器和后置处理器
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    Class<?> targetType = determineTargetType(beanName, mbd);
    if (targetType != null) {
        // 前置处理器
        bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
        if (bean != null) {
            // 后置处理器 
            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
        }
    }
    // 省略其他代码
    return bean;
}

// 前置处理器
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
            if (result != null) {
                return result;
            }
        }
    }
    return null;
}
// 后置处理器
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {
    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        result = beanProcessor.postProcessAfterInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}

5.型変換

上記の手順を実行すると、Beanがシングルトン、プロトタイプ、またはその他のスコアであるかどうかに関係なく、Beanインスタンスが取得されます。つまり、ここにBeanインスタンスがあります。インスタンスを取得したら、型変換を続行する必要があります。つまり、BeanがStringであるが、requiredTypeがIntegerの場合、型変換が必要です。


if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
    return getTypeConverter().convertIfNecessary(bean, requiredType);
}

// 获取类型转换器
public TypeConverter getTypeConverter() {
    TypeConverter customConverter = getCustomTypeConverter();
    if (customConverter != null) {
        return customConverter;
    }
    else {
        SimpleTypeConverter typeConverter = new SimpleTypeConverter();
        typeConverter.setConversionService(getConversionService());
        registerCustomEditors(typeConverter);
        return typeConverter;
    }
}

// 类型的转换
public <T> T convertIfNecessary(Object value, Class<T> requiredType, Field field){
    return doConvert(value, requiredType, null, field);
}

private <T> T doConvert(Object value, Class<T> requiredType, MethodParameter methodParam, Field field){
    if (field != null) {
        return this.typeConverterDelegate.convertIfNecessary(value, requiredType, field);
    }
    else {
        return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);
    }
}

// 正真类型的转换
public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
    Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {
    // 自定义转换器
    PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
    ConversionFailedException conversionAttemptEx = null;
    ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
    if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) 
    {
        TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
        if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
            return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
        }
     }
   }
   // 省略其他代码
    if (requiredType != null) {
    if (convertedValue != null) {
        // 类型为 class
        if (Object.class == requiredType) {
            return (T) convertedValue;
        }
        // 类型为数组
        else if (requiredType.isArray()) {
            if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
            }
            return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
        }
        // 类型为集合
        else if (convertedValue instanceof Collection) {
            convertedValue = convertToTypedCollection((Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);
            standardConversion = true;
        }
        // 类型为 map
        else if (convertedValue instanceof Map) {
            convertedValue = convertToTypedMap( (Map<?, ?>) convertedValue, propertyName, requiredType, typeDescriptor);
            standardConversion = true;
        }
        if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
            convertedValue = Array.get(convertedValue, 0);
            standardConversion = true;
        }
        // String
        if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
            return (T) convertedValue.toString();
        }
        // String
        else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
            if (conversionAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
                Constructor<T> strCtor = requiredType.getConstructor(String.class);
                return BeanUtils.instantiateClass(strCtor, convertedValue);
            }
            String trimmedValue = ((String) convertedValue).trim();
            if (requiredType.isEnum() && "".equals(trimmedValue)) {
                return null;
            }
            convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
            standardConversion = true;
        }
        // number
        else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
            convertedValue = NumberUtils.convertNumberToTargetClass(
                    (Number) convertedValue, (Class<Number>) requiredType);
            standardConversion = true;
        }
    }
    else {
        if (javaUtilOptionalEmpty != null && requiredType == javaUtilOptionalEmpty.getClass()) {
            convertedValue = javaUtilOptionalEmpty;
        }
    }
    // 省略其他代码
    return (T) convertedValue;
}

この時点で、getBeanを介して正しいBeanを取得できます。

上記はgetBeanメソッドのロジックです。主に、FactoryBeanを介してBeanを作成することもでき、beanNameを&で始めることもできることを知っておく必要があります。

おすすめ

転載: blog.51cto.com/15077536/2608557