CDI @Injectを使用してスプリングビーンを注入します
-
30-09-2019 - |
質問
スプリングコンテキストで定義された豆をCDI管理コンポーネントに注入しようとしていますが、成功していません。豆は注入されませんが、代わりに注入を実行するたびに新しいインスタンスが作成されます。私の環境は、JBoss Weldを備えたTomcat 7です。
Spring ApplicationContextはstraighforwardです。
<beans>
...
<bean id="testFromSpring" class="test.Test" />
...
</bean>
CDIマネージドビーンは次のようになります:
@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>
ただし、アクセスすると test
JSFページ内からのプロパティ、新しいページ 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
春のコンテキストで定義された豆から値を返します。ただし、2番目の出力は、毎回 getTest
の方法 test
コンポーネントが呼び出され、新しい Test
予想通り、スプリングコンテキストからインスタンスを使用する代わりに、インスタンスが作成および注入されます。
それで、この行動の理由は何ですか?
春のコンテキストから豆をCDIマネージドビーンに注入するにはどうすればよいですか?
また、春のコンテキストで定義された名前を使用して予選を使用してみましたが、豆が見つからないことを示す例外がスローされています。
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;
解決
Pascalは、Springが管理するものを溶接豆に注入できないことです(またはその逆)。
しかし、スプリングビーンズを手に入れて溶接するプロデューサーを定義できます。これは極端なハックのように聞こえます、ところで、私はあなたが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上記のタイプセーフをより多くすることができます。豆を名前で取得する代わりに、反射を通じて注入ポイントの一般的なタイプを取得し、春のコンテキストでそれを調べることができます。
他のヒント
溶接は、溶接(インスタンス化されていない)を溶接(あなたの場合はスプリングビーン)によって注入できるとは思いません。
JBoss Snowdropプロジェクトもあります。 TomcatでJBoss Weldで動作するかどうかはわかりません。ドキュメントでは、JBoss 5、6、および7でのみ説明しています。 http://docs.jboss.org/snowdrop/2.0.0.final/html/ch03.html#d0e618 jboss-spring.xmlで宣言された豆を @injectの代わりに@springでマークされた場所に注入します。しかし、私自身はありません、YMMV。