2


Springプロジェクトでコントラクトを定義し、デプロイ中にコントラクト(インターフェイスのセット)を実装する外部JARを自動配線したいという要件があります。可能な限り柔軟になるように、外部JARをSpringに依存するように強制したくありません。Springプロジェクトで、コントラクトインターフェイスを使用している場所で、外部JARのクラスを自動配線置換として使用することはできませんか?例を挙げて説明しましょう。

Spring project:
@Controller
public class MyController {
     @Autowired
     private MyInterface interface;
}

これで、コントラクトインターフェイスを実装するJARがクライアントによって提供される可能性があり、パッケージ名を事前に知らない可能性があり、Spring以外のプロジェクトである可能性もあるため、@Componentアノテーションで宣言されない可能性があります。

例えば

public class CustomerClass implements MyInterface {
}

今私の春のプロジェクトでは、MyInterfaceの代わりにCustomerClassを注入する方法はありますか?私の質問が明確であることを願っています。

ありがとう

4

3 に答える 3

2

@Paddy、従来のXMLの方法で同じ目標を達成できるかどうかについての懸念について。以下は、それを実現する方法を示すサンプル コードです。注: コントローラーが MyInterface への参照を保持しているため、インターフェイスMyInterfaceこのように動的にすることはできません。

Spring アプリケーション コンテキスト構成:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="locations" value="classpath:test.properties" />
</bean>
<bean id="myInterface" class="${myinterface.impl}"></bean>

MyInterface と 2 つの異なる実装クラス

package au.net.test;

public interface MyInterface {

    public String getMessage();
}

public class MyClass1 implements MyInterface{

    public String getMessage(){
        return "message from class 1";
    }
}

public class MyClass2 implements MyInterface{

    public String getMessage() {
        return "message from class 2";
    }   
}

classpath の下の test.properties ファイル (ant スクリプトと maven プロファイルを使用してプロパティ値を変更できます)

myinterface.impl=au.net.test.MyClass2

Web レイヤー コントローラー (動的 Bean 候補に基づいて実装クラスを注入できます)

@Autowired
private MyInterface myInterface;
于 2013-02-04T11:28:45.920 に答える
1

わかりました、私はあなたにポイントを得ました。その場合、質問のタイトルは「SpringContainerによって動的タイプのクラスを注入する方法」になります。次に、解決策について説明します。まず、完全修飾クラス名を保持するために、ある種のプロパティが必要です。そして、実行時にカスタムBeanをSpringコンテナに登録できます。

ClassPathXmlApplicationContext applicationContext = new    ClassPathXmlApplicationContext("classpath:/applicationContext*");
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
            //register your bean at runtime 
        beanFactory.registerBeanDefinition("myClass", BeanDefinitionBuilder.rootBeanDefinition("au.net.test.DynamicClass").getBeanDefinition());
            //retrieve you bean from spring container
        Object myBean = applicationContext.getBean("myClass");
            //cast to the type of your bean class or interface (be really careful)
        System.out.println(((DynamicClass)myBean).getMessage());


package au.net.test;
//this is the bean gets looked up and injected at runtime
public class DynamicClass {
    //simple method to verify it is working
    public String getMessage(){
        return "this is testing message";
    }
}

上記のコードでは、ハードコーディングではなく、「au.net.test」プロパティ値を駆動する必要があります。

于 2013-02-04T09:09:59.310 に答える
0

factory-bean を factory-method と一緒に使用できます

<bean id="serviceProvider" class="package.ServiceProvider">

<bean id="myInterface"
      factory-bean="serviceProvider"
      factory-method="createMyInterfaceInstance"/>
//it might or might not to be a singleton factory, depending on your requirement.
public class ServiceProvider{
  private static MyInterface myInterface= new CustomerClass();

  private ServiceProvider() {}

  public MyInterface createMyInterfaceInstance() {
    return myInterface;
  }
}

したがって、基本的にここでの考え方は、インスタンスを作成するための独自のファクトリ クラスとファクトリ メソッドを作成する必要があるということです。ファクトリによっては、シングルトンまたはプロトタイプ インスタンスが作成される場合があります。そして、残りのジョブはSpring Containerに任せてください。

于 2013-02-04T06:44:38.547 に答える