41

@EntitySpring の依存性注入を使用して JPA に Bean を注入することは可能ですか?

@Autowire ServletContext を試みましたが、サーバーは正常に起動しましたが、Bean プロパティにアクセスしようとすると NullPointerException を受け取りました。

@Autowired
@Transient
ServletContext servletContext;
4

3 に答える 3

53

@Configurableここで説明されているように、Springコンテナーによって管理されていないオブジェクトに依存関係を注入できます。 .

これまでに気付いたように、適切な AspectJ ウィービング構成を使用しない限り、Spring はオペレーター@Configurableを使用して作成されたオブジェクトに依存関係を注入しません。new実際、 からオブジェクトを取得しない限り、オブジェクトに依存関係を注入しませんApplicationContext。単純な理由は、オブジェクトの存在を認識していないからです。エンティティに で注釈を付けたとしても@Component、そのエンティティのインスタンス化は、ユーザーnewまたは Hibernate などのフレームワークによる操作によって実行されます。注釈は単なるメタデータであることを忘れないでください。誰もそのメタデータを解釈しなければ、動作を追加したり、実行中のプログラムに影響を与えたりすることはありません。

そうは言ってもServletContext、エンティティに a を注入しないことを強くお勧めします。エンティティはドメイン モデルの一部であり、サーブレット ベースの Web 配信レイヤーなどの配信メカニズムから分離する必要があります。コマンドライン クライアントまたは ServletContext を含まない他の何かによってアクセスされたときに、そのエンティティをどのように使用しますか? その ServletContext から必要なデータを抽出し、従来のメソッド引数を介してエンティティに渡す必要があります。このアプローチにより、はるかに優れた設計を実現できます。

于 2013-07-16T22:40:40.783 に答える
22

はい、もちろんできます。<bean>以下に示すように、タグを使用して (一部の spring-context.xml で)宣言的に、または注釈を介して、エンティティが Spring マネージド Bean としても登録されていることを確認する必要があります。

アノテーションを使用すると、エンティティにマークを付けることができます(または、 DAO の自動例外変換を有効にし、JPA に干渉する場合と干渉しない場合がある@Component、より具体的なステレオタイプ)。@Repository

@Entity
@Component
public class MyJAPEntity {

  @Autowired
  @Transient
  ServletContext servletContext;
  ...
}

エンティティに対してこれを行ったら、エンティティが Bean として取得され、依存関係が自動配線されるように、Spring によってスキャンされるようにパッケージ (または祖先パッケージ) を構成する必要があります。

<beans ... xmlns:context="..." >
  ...
  <context:component-scan base-package="pkg.of.your.jpa.entities" />
<beans>

編集:(最終的に機能したものとその理由)

  • ServletContext スタティックを作る。( @Autowiredを削除)

    @Transient
    private static ServletContext servletContext;
    

JPA は別のエンティティ インスタンスを作成しているため、つまり Spring マネージド Bean を使用していないため、コンテキストを共有する必要があります。

  • @PostConstruct init()メソッドを追加します。

    @PostConstruct
    public void init() {
        log.info("Initializing ServletContext as [" +
                    MyJPAEntity.servletContext + "]");
    }
    

これinit()は、エンティティがインスタンス化されると起動し、ServletContext内部を参照することによって、まだ注入されていない場合は静的プロパティに注入を強制します。

  • インスタンスメソッドに移動@Autowiredしますが、静的フィールドを内部に設定します。

    @Autowired
    public void setServletContext(ServletContext servletContext) {
        MyJPAEntity.servletContext = servletContext;
    }
    

以下の私の最後のコメントを引用して、なぜこれらの悪ふざけを採用しなければならないのかを答えます。

JPA は Spring コンテナーを使用してエンティティーをインスタンス化しないため、必要なことを行うためのきれいな方法はありません。JPA は、エンティティのライフサイクルをインスタンス化して管理し (Spring とは完全に分離)、エンティティ関係のみに基づいて DI を実行する個別の ORM コンテナーと考え​​てください。

于 2013-05-10T18:58:21.180 に答える