Java Spring Web 应用程序中控制器、服务、存储库的范围?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18533962/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 08:50:26  来源:igfitidea点击:

Scope of Controllers ,Service,Repository in Spring Web Application?

javamultithreadingspringhibernatespring-mvc

提问by beinghuman

I am creating a web application using spring ,hibernate. Suppose multiple users wants to register.I will create a registration bean(prototype or request or session scoped) and autowire it in Controller.

我正在使用 spring 和 hibernate 创建一个 Web 应用程序。假设多个用户想要注册。我将创建一个注册 bean(原型或请求或会话范围)并在控制器中自动装配它。

Now I am passing this bean to Registration Service(annotated with "@transactional" annotation) which is also autowired in the controler. This service will pass recieved registeration bean object to DAO(This DAO is autowired in the service)If service and DAO are singelton would'nt the requests be mixed up for multiple users?

现在我将这个 bean 传递给注册服务(用“@transactional”注释进行注释),它也在控制器中自动装配。此服务将接收到的注册 bean 对象传递给 DAO(此 DAO 在服务中自动装配)如果服务和 DAO 是单一的,那么多个用户的请求不会被混淆吗?

Here is what I have done :I have created the scope of service and DAO as "request". Is this the right approach? or what else could I do to make the service and DAO singelton?

这是我所做的:我将服务和 DAO 的范围创建为“请求”。这是正确的方法吗?或者我还能做些什么来使服务和 DAO 成为单一的?

My logic behind request scoped: The reason for making service and DAO as request scoped is if multiple users call registerationService.registerUser(bean); from the controller at same time and scope is singelton then there would be no consistency coz there one object's methods are called with different inputs.

我的请求范围背后的逻辑:将服务和 DAO 作为请求范围的原因是如果多个用户调用 registerationService.registerUser(bean); 同时来自控制器并且范围是单一的,那么将没有一致性,因为使用不同的输入调用一个对象的方法。

LET ME KNOW WHERE I AM WRONG.

让我知道我哪里错了。

Registeration Bean

注册豆

@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


}

Controller

控制器

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();
    }
}

Concrete DAO

具体的DAO

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


}

采纳答案by Olaf

The services and DAOs should be stateless. This would allow you to configure them as Spring singletons. I hope this is what you mean when you say "singleton".

服务和 DAO 应该是无状态的。这将允许您将它们配置为 Spring 单例。我希望这就是您说“单身”时的意思。

All threading concerns, including the thread pooling, will be taken care of by the infrastructure: your web/Java EE server and Spring DI.

所有线程问题,包括线程池,都将由基础设施处理:您的 Web/Java EE 服务器和 Spring DI。

回答by Pratik Tari

you should inject your service, dao objects to your controllers using spring and all beans injected through spring are singletons by default

您应该使用 spring 将您的服务、dao 对象注入到您的控制器中,并且默认情况下,所有通过 spring 注入的 bean 都是单例的

回答by Sotirios Delimanolis

Unless your DAOs need instance fields, there's no need for them to be request scoped. As long as your Hibernate Sessionis retrieved with Session#getCurrentSession(), which is thread bound, a single DAO instance to handle all requests is fine. The same applies for Service classes and Controllers.

除非您的 DAO 需要实例字段,否则不需要将它们设置为请求范围。只要您的 HibernateSession是用 来检索的Session#getCurrentSession(),它是线程绑定的,处理所有请求的单个 DAO 实例就可以了。这同样适用于服务类和控制器。

As for your statement

至于你的说法

which I think slow down the response to the user

我认为这会减慢对用户的响应

That is not always true, depending on how heavy the object is. The Servlet container and your Spring DispatcherServletare instantiating so many objects anyway. You shouldn't see a big change.

这并不总是正确的,这取决于物体的重量。DispatcherServlet无论如何,Servlet 容器和您的 Spring正在实例化如此多的对象。你不应该看到很大的变化。

Creating a pool of these objects would be overkill. Note: Those wouldn't be Thread pools, just object pools.

创建这些对象的池将是矫枉过正。注意:那些不会是 Thread pools,只是对象池。

回答by Ashish Chaurasia

Annotate your service class with @Service and Dao class with @Repository .

使用 @Service 注释您的服务类,使用 @Repository 注释 Dao 类。

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

it will automatically creates singleton bean for your class

它会自动为你的类创建单例 bean

回答by Kid101

I'm going through the same confusion, however, after reading all the links. This is what I've understood(Please correct me If I'm wrong) The registration bean will be of type prototype or request because there can be two or more simultaneous requests for registration and if that object is singleton then will be overwriting each other's value.

然而,在阅读了所有链接后,我正在经历同样的困惑。这就是我所理解的(如果我错了,请纠正我)注册 bean 将是原型或请求类型,因为可以有两个或多个同时注册请求,如果该对象是单例对象,则将覆盖彼此的价值。

THE DAO and service will be singleton because they are just methods and don't modify any global variable that is to be used by other threads. They have their own stack.

DAO 和服务将是单例的,因为它们只是方法,不会修改其他线程使用的任何全局变量。他们有自己的堆栈。