2013-08-30 7 views
8

私は春、冬眠を使用してWebアプリケーションを作成しています。 複数のユーザーが登録したいと仮定します。登録Bean(プロトタイプまたは要求またはセッションスコープ)を作成し、Controllerでautowireします。Spring Webアプリケーションのコントローラ、サービス、リポジトリの範囲?

このBeanは、登録サービス(「@transactional」アノテーションが付いている)に渡しています。このサービスは、コントロールで自動実行されます。 このサービスは受信した登録BeanオブジェクトをDAOに渡します(このDAOはサービス内で自動実行されます)。サービスとDAOが複数のユーザーのために要求を混同しないなら、

これは私がやったことです:サービスの範囲とDAOを「要求」として作成しました。 これは正しいアプローチですか?サービスやDAOをシェルトンにするために他に何ができるのでしょうか?

リクエストの有効範囲の背後にある: サービスとDAOをリクエストスコープにする理由は、複数のユーザーがコールする場合です。 registerationService.registerUser(bean);スコープがシングルトンであれば、そこには一貫性がありません。オブジェクトのメソッドが異なる入力で呼び出されます。

私は間違っていると知っています。

Registeration豆

@Component(value="registerBean") 
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "request") 
public class RegisterBean { 


@NotNull 
private String userName; 

private String lastName; 
@NotNull 
private String firstName; 

String email_address; 
String password; 
String confirmPassword; 
String gender; 

//getters and setters 


} 

コントローラ

package com.ClickToShop.controllers; 






@Controller 
    @SessionAttributes("user_info") 
    public class LoginPageController { 




     RegisterBean registerBean;//used 

     RegisterationService registerationService;//used 



     @Autowired 
     @Qualifier("registerationService") 
     public void setRegisterationService(RegisterationService registerationService) { 
      this.registerationService = registerationService; 
     } 




     @Autowired 
     @Qualifier("registerBean") 
     public void setRegisterBean(RegisterBean registerBean) { 
      this.registerBean = registerBean; 
     } 



     @ModelAttribute(value = "registerBean") 
     RegisterBean returnModelAttribute() { 
      return registerBean; 
     } 

     @RequestMapping(value = "/login-page.html") 
     public String showLoginPage() { 
    System.out.println("Showing login page"); 
    System.out.println(registerBean); 
      return "login-page"; 

     } 



     @RequestMapping(value = "/newuser-register", method = RequestMethod.POST) 
     public String registernewuser(@ModelAttribute("registerBean") @Valid RegisterBean bean, BindingResult result,final RedirectAttributes redirectAttr) 
       throws NoSuchAlgorithmException, UnsupportedEncodingException { 
      //some validation code 

    registerationService.registerUser(bean); 



        return "redirect:successRegisteration"; 
       } 


     } 




    } 




Service Layer 

     @Service("registerationService") 
     @Transactional 
     @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS,value="request") 

     public class UserServiceImpl implements RegisterationService { 


      private User_Details_Pojo userToRegisterPojo; 
      private AbstractHibernateDAO UserDAO; 


      @Autowired 
      public void setUserDAO(AbstractHibernateDAO userDAO) { 
       UserDAO = userDAO; 
      } 



      @Autowired 
      @Qualifier("userToRegisterPojo") 
      public void setUserToRegisterPojo(User_Details_Pojo userToRegisterPojo) { 
       this.userToRegisterPojo = userToRegisterPojo; 
      } 




     //main implementation code starts here 

      @Override 

      public void registerUser(Object userBean) { 
       RegisterBean bean=(RegisterBean) userBean; 
       //bean or model is converted to pojo 


      UserDAO.save(userToRegisterPojo);//calling DAO with specified pojo 



      } 



     } 

DAO:

public abstract class AbstractHibernateDAO<T extends Serializable> { 

    public Class<T> clazz;//class object reference 

    protected SessionFactory mysessionFactory; 


    @Autowired 
    public void setMysessionFactory(SessionFactory mysessionFactory) { 
     this.mysessionFactory = mysessionFactory; 
    } 

    public T findOneByName(final String name){ 

     return (T) getCurrentSession().createQuery("from "+clazz.getName()).uniqueResult(); 
    } 


    public void setClazz(final Class<T> clazzToSet) { 
     this.clazz = clazzToSet; 
    } 

    public T findOne(final Long id) { 
     return (T) getCurrentSession().get(clazz, id); 
    } 

    @SuppressWarnings("unchecked") 
    public List<T> findAll() { 
     return getCurrentSession().createQuery("from " + clazz.getName()).list(); 
    } 

    public void save(final T entity) { 
     getCurrentSession().merge(entity); 
    } 

    public void update(final T entity) { 
     getCurrentSession().update(entity); 
    } 

    public void delete(final T entity) { 
     getCurrentSession().delete(entity); 
    } 

    public void deleteById(final Long entityId) { 
     final T entity = findOne(entityId); 
     delete(entity); 
    } 

    protected Session getCurrentSession() { 

     return mysessionFactory.getCurrentSession(); 
    } 
} 

コンクリートDAO

@Repository 
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS,value="request") 
public class UserDAO extends AbstractHibernateDAO<User_Details_Pojo>{ 


} 

答えて

2

サービスとDAOはステートレスでなければなりません。これにより、それらをSpringシングルトンとして構成することができます。私はこれがあなたが「シングルトン」と言ったときの意味であると願っています。

スレッドプーリングを含むすべてのスレッドの問題は、インフラストラクチャによって処理されます。ウェブ/ Java EEサーバーとSpring DIです。

+0

複数のユーザーが登録したいと仮定します。すべてのユーザーに対して登録Bean(プロトタイプ、リクエスト、セッションスコープ)を作成します。このBeanを登録サービスに渡します(「@トランスクリプト」注釈付き)。 DAOに登録Beanオブジェクトを追加する必要があります。サービスとDAOが複数のユーザーにリクエストを混在させることはありませんか? – beinghuman

+0

DAOで自分自身でHibernateセッションを管理しようとしている場合を除き、これは起こりません。 SpringはスレッドごとにHibernateセッションを含むトランザクションコンテキストを割り当てます。 Webサーバーは、各ユーザーの要求ごとに、プールからスレッドを取得/取得します。したがって、2人のユーザーからの登録Beanは別々のメモリ位置に「生きて」おり、別々のHibernateセッションを介して処理され、別々のDB接続上の別々のトランザクションでデータベースに書き込まれます。 – Olaf

+0

これは私があなたにこのことを説明することができるかどうかを明らかにするでしょう。複数の要求が来ます.Webサーバは、各request.theseスレッドごとに別個のスレッドを割り当てます。registerbeanをプロトタイプした同じシングルトンコントローラを使用します。シングルトンコントローラがプロトタイプのBeanを使用する場合、このシングルトンコントローラの初期化中に、その依存するPrototype Beanも作成されます。すべてのリクエストが単一のBeanにアクセスします。私を教えてください。 – beinghuman

0

あなたはあなたのサービスにDAOオブジェクトをスプリングで注入する必要があります。スプリングを介して注入されるすべてのBeanはデフォルトでシングルトンです。

+0

このような回答を期待していません。私の質問は不明ですか?私に知らせてください。 – beinghuman

+0

通常、リクエストごとにサービスとDAOオブジェクトを作成しません。また、スレッドプールを作成する必要もありません。これらのオブジェクトは、リクエストごとにこれらの2つのオブジェクトをインスタンス化しても、インスタンス自体に大きな依存性がない限り、プロセスを大幅に遅くすることはありません –

+0

これは私が何かを逃したと思います。このような状況のために私はシングルトンサービスとDAOオブジェクトを使うことはできません。 – beinghuman

2

DAOにインスタンスフィールドが必要な場合を除き、要求スコープにする必要はありません。あなたのHibernate SessionがスレッドにバインドされているSession#getCurrentSession()で取得されている限り、すべての要求を処理する単一のDAOインスタンスは問題ありません。同じことがサービスクラスとコントローラにも当てはまります。私は、オブジェクトがどのように重いによっては、常に真ではないユーザー

に応じてダウン遅いと思うあなたの声明

については

。サーブレットコンテナとSpring DispatcherServletは、とにかく多くのオブジェクトをインスタンス化しています。大きな変化は見られません。

これらのオブジェクトのプールを作成することは過度の作業です。注:スレッドプール、オブジェクトプールだけではありません。

+0

複数のユーザーが登録したいと仮定します。すべてのユーザーに対して登録Bean(プロトタイプ、リクエスト、セッションスコープ)を作成します。このBeanを登録サービス(@transactionalアノテーションで注釈)に渡します。このサービスは、 DAOへのオブジェクト。サービスとDAOが複数のユーザーのためにリクエストが混在しないのであれば? – beinghuman

+0

@Nikhil:いいえ。シングルトンサービスとdaosはデフォルトです。インスタンスメンバーの個々のリクエストに固有のものがない限り、正常に動作します。リクエスト固有のものはメソッドの引数とローカル変数に入れておき、残りの部分はSpringが処理します。 –

+0

@NathanHughesオラフの答えで私のコメントをチェックしてください。 – beinghuman

3

サービスクラスに@ServiceとDaoクラスを@Repositoryで注釈を付けます。

<context:component-scan base-package="x.y.z.service, x.y.z.dao" /> 

それは自動的に私はすべてのリンクを読んだ後、しかし、同じ混乱を通じてつもりだあなたのクラス

0

のシングルトンBeanを作成します。 これは私が理解したものです(私が間違っている場合は私に修正してください) 登録Beanは、登録のための複数の同時リクエストがあり、そのオブジェクトがシングルトンの場合は上書きされるため、プロトタイプまたはリクエストタイプですお互いの価値。

DAOとサービスは単なるメソッドであり、他のスレッドが使用するグローバル変数を変更しないため、シングルトンになります。彼らは自分のスタックを持っています。

+0

はい。あるいは多少異なるようにするには、マルチスレッドコンテキストで変更されずに共有されるシングルトンは、インスタンス変数finalまたはコンストラクタロードによってステートレスにする必要があります。 – theRiley

関連する問題