10

Spring コンテキストで定義された Bean を CDI 管理コンポーネントに注入しようとしていますが、うまくいきません。Bean は注入されません。代わりに、注入が実行されるたびに新しいインスタンスが作成されます。私の環境は、JBoss Weld を使用した Tomcat 7 です。

Spring ApplicationContext は簡単です。

<beans>
  ...
  <bean id="testFromSpring" class="test.Test" />
  ...
</bean>

CDI マネージド Bean は次のようになります。

@javax.inject.Named("testA")
public class TestA {

  @javax.inject.Inject
  private Test myTest = null;

  ...

  public Test getTest() {
    return this.myTest;
  }

}

これは私のfaces-config.xml

<faces-config xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" version="2.0">
  <application>
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
  </application>
</faces-config>

ただし、testJSF ページ内からプロパティにアクセスTestすると、アクセスが発生するたびに新しいインスタンスが作成されます。これは簡単な例です:

<html>
  ...
  <p>1: <h:outputText value="#{testFromSpring}" /></p>
  <p>2: <h:outputText value="#{testA.test}" /></p>
  ...

次の出力が得られます。

1: test.Test@44d79c75
2: test.Test@53f336eb

リフレッシュ後:

1: test.Test@44d79c75
2: test.Test@89f2ac63

最初の出力が正しいことがわかります。ページを頻繁に更新してもtestFromSpring、Spring コンテキストで定義された Bean から値が返されます。getTestただし、2 番目の出力は、コンポーネントのメソッドtestが呼び出されるたびにTest、Spring コンテキストのインスタンスを使用する代わりに、新しいインスタンスが作成されて注入されることを明確に示しています。

では、この行動の理由は何ですか?

Spring コンテキストから CDI マネージド Bean に Bean を注入するにはどうすればよいですか?

また、Spring コンテキストで定義された名前を使用して修飾子を使用しようとしましたが、Bean が見つからないことを示す例外がスローされました。

org.jboss.weld.exceptions.DeploymentException: WELD-001408 Injection point has unsatisfied dependencies.  Injection point:  field test.TestA.myTest;  Qualifiers:  [@javax.inject.Named(value=testFromSpring)]

コードの

@javax.inject.Named("testA")
public class TestA {

  @javax.inject.Inject
  @javax.inject.Named("testFromSpring")
  private Test myTest = null;
4

3 に答える 3

15

パスカルは、スプリングによって管理されるものを溶接ビーンに注入できない (またはその逆) ことは正しいです。

ただし、Spring Bean を取得して Weld に渡すプロデューサーを定義できます。ところで、これは極端なハックのように聞こえますが、1 つのプロジェクトで両方のフレームワークを使用することになっているとは思いません。1 つを選択し、もう 1 つを削除します。そうしないと、複数の問題が発生します。

これがどのように見えるかです。

@Qualifier
@Retention(Runtime)
public @interface SpringBean {
     @NonBinding String name();
}


public class SpringBeanProducer {

    @Produces @SpringBean
    public Object create(InjectionPoint ip) {
         // get the name() from the annotation on the injection point
         String springBeanName = ip.getAnnotations()....

         //get the ServletContext from the FacesContext
         ServletContext ctx = FacesContext.getCurrentInstance()... 

         return WebApplicationContextUtils
              .getRequiredWebApplication(ctx).getBean(springBeanName);
    }
}

次に、次のことができます。

@Inject @SpringBean("fooBean")
private Foo yourObject;

PS上記をよりタイプセーフにすることができます。Bean を名前で取得する代わりに、リフレクションを通じて注入ポイントのジェネリック型を取得し、Spring コンテキストで検索できます。

于 2010-11-10T12:15:41.930 に答える
4

Weld は、Weld によって管理 (インスタンス化) されていないもの (あなたの場合は Spring Bean) を注入できるとは思いません。

于 2010-11-10T11:46:45.540 に答える
2

JBossSnowdropプロジェクトもあります。TomcatのJBossWeldで動作するかどうかはわかりませんが、ドキュメントにはJBoss 5、6、7についてのみ説明されています。http://docs.jboss.org/snowdrop/2.0.0.Final/html/によるとch03.html#d0e618 jboss-spring.xmlで宣言されたBeanを、@Injectではなく@Springでマークされた場所に注入します。YMMV、私自身は経験がありません。

于 2011-11-06T23:09:07.073 に答える