カスタムBeanWrapper実装を使用してアプリケーションコンテキストをロードする方法はありますか

デイブ・グリフィス:

Scalaコンポーネントへのセッターインジェクションを使用してSpringを使用できるようにしたいと思います。残念ながら、Scalaのネイティブセッターの名前は、JavaBeans標準とfoo_=異なり、ではありませんsetFooScalaはこれに対していくつかの回避策を提供します。これは、JavaBeansのセッター/ゲッターとネイティブのScalaのセッター/ゲッターの作成を強制するアノテーションですが、注入するすべてのコンポーネントにアノテーションを付ける必要があります。BeanWrapperSpringで使用されているものを、Scalaスタイルのゲッターとセッターの処理方法を知っているものでオーバーライドすると、はるかに便利になります

そのようなことを行う方法や、それが実行可能かどうかについての文書も、それを実行している他の人のオンライン例もないようです。ソースに飛び込む前に、私はここで確認すると思いました

Georgy Bolyuba:

AbstractAutowireCapableBeanFactory(BeanWrapperでのほとんどの作業が行われる)ようにハードコードされているように見えますBeanWrapperImplそこに拡張ポイントはありません。順番にBeanWrapperImpl使用CachedIntrospectionResultsする用途Introspectorこれらの依存関係を構成する方法はないようです。標準の拡張ポイントを使用することができます:BeanPostProcessorまたはBeanFactoryPostProcessor

just BeanPostProcessor使用しても機能しません。

<bean id="beanForInjection" class="com.test.BeanForInjection">
    <property name="bean" ref="beanToBeInjected"/>        
</bean>

BeanForInjectionScalaクラスはどこですか

package com.test
import com.other.BeanToBeInjected

class BeanForInjection {
    var bean : BeanToBeInjected = null;
}

そしてBeanToBeInjected私たちは前に、我々は、例外をキャッチする、注入したいBeanでBeanPostProcessorのステップへのチャンスがあります。豆は、任意のコールバックの前に値が移入されますBeanPostProcessorと呼ばれます。

しかしBeanFactoryPostProcessor、Scalaのようなセッターを通じて注入されることが予想されるプロパティを「非表示」にして、後者に適用することができます。

これはなんとかします:

package com.other;

import ...

public class ScalaAwareBeanFactoryPostProcessor implements BeanFactoryPostProcessor, PriorityOrdered {

    ... PriorityOrdered related methods...

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        String[] beanNames = beanFactory.getBeanDefinitionNames();
        for (String currentName : beanNames) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(currentName);
            processScalaProperties(beanDefinition);
        }
    }

    protected void processScalaProperties(BeanDefinition beanDefinition) {
        String className = beanDefinition.getBeanClassName();
        try {
            Set<PropertyValue> scalaProperties = new HashSet<PropertyValue>();
            for (PropertyValue propertyValue : beanDefinition.getPropertyValues().getPropertyValueList()) {
                String scalaSetterName = ScalaAwarePostProcessorUtils.getScalaSetterName(propertyValue.getName());

                BeanInfo beanInfo = getBeanInfo(className);
                PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
                MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();
                for (MethodDescriptor md : methodDescriptors) {

                    if (scalaSetterName.equals(md.getName())) {
                        boolean isScalaProperty = true;
                        for (PropertyDescriptor pd : propertyDescriptors) {
                            if (propertyValue.getName().equals(pd.getName())) {
                                isScalaProperty = false;
                            }
                        }
                        if (isScalaProperty) {
                            scalaProperties.add(propertyValue);
                        }
                    }
                }
            }

            if (!scalaProperties.isEmpty()) {
                beanDefinition.setAttribute(ScalaAwarePostProcessorUtils.SCALA_ATTRIBUTES_KEY, scalaProperties);
            }

            for (PropertyValue propertyValue : scalaProperties) {
                beanDefinition.getPropertyValues().removePropertyValue(propertyValue);
            }
        } catch (ClassNotFoundException e) {
        } catch (IntrospectionException e) {
        }
    }

    private BeanInfo getBeanInfo(String className) throws ClassNotFoundException, IntrospectionException {
        Class beanClass = Class.forName(className);
        BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);
        cleanIntrospectorCache(beanClass);
        return beanInfo;
    }

    private void cleanIntrospectorCache(Class beanClass) {
        Class classToFlush = beanClass;
        do {
            Introspector.flushFromCaches(classToFlush);
            classToFlush = classToFlush.getSuperclass();
        }
        while (classToFlush != null);
    }
}

この実装は、Beanにプロパティとしてリストされていないプロパティがあり、Scalaのようなセッターもあるかどうかを単にチェックします。このコントラクトに一致するすべてのプロパティがプロパティリストから削除され、Beanの属性として保存されます。ここで必要なのは、すべてのBeanに対してこの属性(存在する場合)をプルして適用することだけです。必要な場所がありますBeanPostProcessor(AutowiredAnnotationBeanPostProcessorはBeanPostProcessorの良い例です)。

package com.other;

public class ScalaAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
    implements PriorityOrdered, BeanFactoryAware {

    private ConfigurableListableBeanFactory beanFactory;

    ... Order related stuff...

    public void setBeanFactory(BeanFactory beanFactory) {
        if (beanFactory instanceof ConfigurableListableBeanFactory) {
            this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
        }
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs,     PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        try {
            InjectionMetadata metadata = findScalaMetadata(beanFactory.getBeanDefinition(beanName), bean.getClass());
            metadata.inject(bean, beanName, pvs);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Injection of Scala dependencies failed", ex);
        }
        return pvs;
    }

    private InjectionMetadata findScalaMetadata(BeanDefinition beanDefinition, Class<?> beanClass) throws IntrospectionException {
        LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();

        Set<PropertyValue> scalaProperties = (Set<PropertyValue>) beanDefinition.getAttribute(ScalaAwarePostProcessorUtils.SCALA_ATTRIBUTES_KEY);
        if (scalaProperties != null) {
            for (PropertyValue pv : scalaProperties) {
                Method setter = ScalaAwarePostProcessorUtils.getScalaSetterMethod(beanClass, pv.getName());
                if (setter != null) {
                    Method getter = ScalaAwarePostProcessorUtils.getScalaGetterMethod(beanClass, pv.getName());
                    PropertyDescriptor pd = new PropertyDescriptor(pv.getName(), getter, setter);
                    elements.add(new ScalaSetterMethodElement(setter, pd));
                }
            }
        }
        return new InjectionMetadata(beanClass, elements);
    }

    private class ScalaSetterMethodElement extends InjectionMetadata.InjectedElement {

        protected ScalaSetterMethodElement(Member member, PropertyDescriptor pd) {
            super(member, pd);
        }

        @Override
        protected Object getResourceToInject(Object target, String requestingBeanName) {
            Method method = (Method) this.member;
            MethodParameter methodParam = new MethodParameter(method, 0);
            DependencyDescriptor dd = new DependencyDescriptor(methodParam, true);
            return beanFactory.resolveDependency(dd, requestingBeanName);
        }
    }
}

コンテキストでこれらの2つのBeanを作成するだけです。

<bean class="com.other.ScalaAwareBeanFactoryPostProcessor"/>

<bean class="com.other.ScalaAwareBeanPostProcessor"/>

注意:

これは最終的な解決策ではありません。クラスでは機能しますが、単純なタイプでは機能しません。

<bean id="beanForInjection" class="com.test.BeanForInjection">
    <property name="bean" ref="beanToBeInjected"/>        
    <property name="name" value="skaffman"/>
</bean>

ソリューションはで機能しますがbean、では機能しませんnameこれは修正できますが、現時点では、@ BeanInfoアノテーションを使用するだけの方がよいでしょう。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

カスタムボタンをクリックする前にファイルをアップロードし、ajaxを使用してそれをコントローラーアクションメソッドに送信する方法はありますか?

分類Dev

Cucumberrunnerを使用してSpringアプリケーションコンテキストをロードする方法

分類Dev

Cucumberrunnerを使用してSpringアプリケーションコンテキストをロードする方法

分類Dev

カスタムアプリケーションでAndroidパターンロック画面を使用するための実用的なソリューションが必要です(ソースコードのリダイレクトではありません)

分類Dev

JavaScript(Vue.js)を使用してJavaアプリケーション(ゲーム)をWebサイトに実装する方法はありますか

分類Dev

アプリケーションコンテキストは常にwarファイルをサーバーにロードする必要がありますか

分類Dev

AWS CDKコードを使用して、ElasticBeanstalkでホストされているWebアプリケーションにセキュリティグループとVPCを割り当てる方法はありますか?

分類Dev

キックスタータースタイルのアプリケーションにStripe.jsを使用する。カードを繰り返してすべて充電する前に、どうすればカードをテストできますか?

分類Dev

カスタムセキュリティロールとカスタムユーザーグループテーブルを作成して、asp.net mvcWebアプリケーションのカスタム承認を実装します

分類Dev

Autowireを使用して手動でロードするSpringアプリケーションコンテキスト

分類Dev

SPAアプリケーション専用のルートを実装するには、どのコードベースを使用しますか?

分類Dev

PDFからテキストをコピーして、テキスト形式を保持する他のアプリケーションに貼り付ける方法は?

分類Dev

カスタムログインプロンプトを使用してGoogleサインインを実装する方法はありますか?

分類Dev

BlenderのPythonスクリプトでアクションキーフレームをコピーして貼り付ける方法はありますか?

分類Dev

プロセススケジューリングを実装する唯一の方法は、ハードウェアタイマーを使用していますか?

分類Dev

C#を使用してコンソールアプリケーションでコマンドまたはプロセスを実行する方法

分類Dev

JUnitは、正しいアプリケーションコンテキストをロードしているにもかかわらず、間違ったデータベースへのアクセスをテストします

分類Dev

2番目のプログラムに入力するときに、プログラム/アプリケーションでテキストをリアルタイムで更新する方法はありますか?

分類Dev

このエラーを解決する方法.....カスタムFirebase通知アプリケーションを実装しようとしています

分類Dev

コードをテストするためにアプリケーションを環境変数から分離する方法はありますか?

分類Dev

Spring:Webappおよびスタンドアロンプログラムでアプリケーションコンテキストを取得する方法

分類Dev

Wineで実行されているアプリケーションにスタートアップキーストロークを送信する方法はありますか?

分類Dev

Ubuntu Dashを「スタートアップアプリケーション」にする方法はありますか?

分類Dev

JVMで実行されているすべてのSpringアプリケーションコンテキストのリストを取得する方法はありますか?

分類Dev

c#(Windowsフォーム)を使用して、Designerからカスタムユーザーコントロール内のコントロールプロパティにアクセスする方法はありますか?

分類Dev

Javaカスタムコレクション実装のテストスイートはありますか?

分類Dev

EmbeddedKafkaを使用すると、すべてのSpock仕様に対してアプリケーションコンテキストが再ロードされます

分類Dev

警告ダイアログの例外「ウィンドウを追加できません-トークンnullはアプリケーション用ではありません」、どのコンテキストを指定する必要がありますか?

分類Dev

Javascriptを使用してhtmlをRCP(E4)アプリケーションとインターフェースする方法はありますか?

Related 関連記事

  1. 1

    カスタムボタンをクリックする前にファイルをアップロードし、ajaxを使用してそれをコントローラーアクションメソッドに送信する方法はありますか?

  2. 2

    Cucumberrunnerを使用してSpringアプリケーションコンテキストをロードする方法

  3. 3

    Cucumberrunnerを使用してSpringアプリケーションコンテキストをロードする方法

  4. 4

    カスタムアプリケーションでAndroidパターンロック画面を使用するための実用的なソリューションが必要です(ソースコードのリダイレクトではありません)

  5. 5

    JavaScript(Vue.js)を使用してJavaアプリケーション(ゲーム)をWebサイトに実装する方法はありますか

  6. 6

    アプリケーションコンテキストは常にwarファイルをサーバーにロードする必要がありますか

  7. 7

    AWS CDKコードを使用して、ElasticBeanstalkでホストされているWebアプリケーションにセキュリティグループとVPCを割り当てる方法はありますか?

  8. 8

    キックスタータースタイルのアプリケーションにStripe.jsを使用する。カードを繰り返してすべて充電する前に、どうすればカードをテストできますか?

  9. 9

    カスタムセキュリティロールとカスタムユーザーグループテーブルを作成して、asp.net mvcWebアプリケーションのカスタム承認を実装します

  10. 10

    Autowireを使用して手動でロードするSpringアプリケーションコンテキスト

  11. 11

    SPAアプリケーション専用のルートを実装するには、どのコードベースを使用しますか?

  12. 12

    PDFからテキストをコピーして、テキスト形式を保持する他のアプリケーションに貼り付ける方法は?

  13. 13

    カスタムログインプロンプトを使用してGoogleサインインを実装する方法はありますか?

  14. 14

    BlenderのPythonスクリプトでアクションキーフレームをコピーして貼り付ける方法はありますか?

  15. 15

    プロセススケジューリングを実装する唯一の方法は、ハードウェアタイマーを使用していますか?

  16. 16

    C#を使用してコンソールアプリケーションでコマンドまたはプロセスを実行する方法

  17. 17

    JUnitは、正しいアプリケーションコンテキストをロードしているにもかかわらず、間違ったデータベースへのアクセスをテストします

  18. 18

    2番目のプログラムに入力するときに、プログラム/アプリケーションでテキストをリアルタイムで更新する方法はありますか?

  19. 19

    このエラーを解決する方法.....カスタムFirebase通知アプリケーションを実装しようとしています

  20. 20

    コードをテストするためにアプリケーションを環境変数から分離する方法はありますか?

  21. 21

    Spring:Webappおよびスタンドアロンプログラムでアプリケーションコンテキストを取得する方法

  22. 22

    Wineで実行されているアプリケーションにスタートアップキーストロークを送信する方法はありますか?

  23. 23

    Ubuntu Dashを「スタートアップアプリケーション」にする方法はありますか?

  24. 24

    JVMで実行されているすべてのSpringアプリケーションコンテキストのリストを取得する方法はありますか?

  25. 25

    c#(Windowsフォーム)を使用して、Designerからカスタムユーザーコントロール内のコントロールプロパティにアクセスする方法はありますか?

  26. 26

    Javaカスタムコレクション実装のテストスイートはありますか?

  27. 27

    EmbeddedKafkaを使用すると、すべてのSpock仕様に対してアプリケーションコンテキストが再ロードされます

  28. 28

    警告ダイアログの例外「ウィンドウを追加できません-トークンnullはアプリケーション用ではありません」、どのコンテキストを指定する必要がありますか?

  29. 29

    Javascriptを使用してhtmlをRCP(E4)アプリケーションとインターフェースする方法はありますか?

ホットタグ

アーカイブ