bean scope

  By default, all beans in the Spring application context are created as singletons. That is, no matter how many times a given bean is injected into other beans, the same instance is injected each time. In most cases, a singleton bean is the ideal solution. The cost of initializing and garbage collecting object instances is reserved for small-scale tasks where it may not be reasonable to keep objects stateless and reuse them repeatedly in an application. Sometimes, you may find that the classes you use are mutable, they hold some state and are therefore unsafe to reuse. In this case, declaring the class as a singleton bean is not a good idea, because the object will be polluted and there will be unexpected problems when it is reused later.

Spring defines a variety of scopes based on which beans can be created, including:

 

Singleton (Singleton): In the entire application, only one instance of the bean is created.
Prototype:
A new bean instance is created each time it is injected or retrieved from the Spring application context.
Session: In a web application, a bean
instance .
Request (Rquest): In a web application, a bean
instance .

  

  Singletons are the default scope, but as mentioned before, this is not suitable for mutable types. If you choose another scope, use the @Scope annotation, which can be used with @Component or @Bean. For example, if you use component scanning to discover and declare beans, then you can use the @Scope annotation on the bean's class to declare it as a prototype bean:

Here, the prototype scope is set using the SCOPE_PROTOTYPE constant of the ConfigurableBeanFactory class. You can of course also use @Scope("prototype") , but using the SCOPE_PROTOTYPE constant is safer and less error-prone. If you want to declare Notepad as a prototype bean in your Java configuration, you can combine @Scope and @Bean to specify the desired scope:

  Likewise, if you use XML to configure beans, you can use the
scope attribute of the <bean> element to set the scope:

1.1 Using session and request scopes

  In web applications, it would be very valuable to be able to instantiate beans that are shared between session and request scopes. For example, in a typical e-commerce application, there might be a bean representing the user's shopping cart. If the shopping cart is a singleton, it will cause all users to add items to the same shopping cart. On the other hand, if the shopping cart is prototype-scoped, adding items to the shopping cart in one place in the application may not be available in another part of the application, because another prototype-scoped injection is here. shopping cart. As far as the shopping cart bean is concerned, session scope is the most appropriate because it is most relevant to a given user . To specify session scope, we can use the @Scope annotation, which is used in the same way as specifying prototype scope:

  Here, we set the value to the SCOPE_SESSION constant in the WebApplicationContext (its value is session). This tells Spring to create a ShoppingCart for each session in the web application. This will create multiple instances of the ShoppingCart bean, but only one instance will be created for a given session. This bean is effectively a singleton for operations related to the current session. Note that @Scope also has a proxyMode property, which is set to ScopedProxyMode.INTERFACES. This property solves the problem with injecting session or request scoped beans into singleton beans. Before describing the proxyMode property , let's take a look at the scenario of the problem that proxyMode solves.

  Suppose we want to inject the ShoppingCart bean into the Setter method of the singleton StoreService bean as follows:

 

Because StoreService is a singleton bean, it will be created when the Spring application context is loaded . When it is created, Spring will try to inject the ShoppingCart bean into the setShoppingCart() method. But the ShoppingCart bean is session scoped and doesn't exist at this time. An instance of ShoppingCart will not appear until a user enters the system and a session is created.

 

Additionally, there will be multiple instances of ShoppingCart in the system: one for each user. We don't want Spring to inject a fixed instance of ShoppingCart into the StoreService. What we want is that when the StoreService handles the shopping cart function, it uses the ShoppingCart instance that happens to be the one for the current session .

 

Instead of injecting the actual ShoppingCart bean into the StoreService, Spring injects a proxy to the ShoppingCart bean, as shown in Figure 3.1. This proxy will expose the same methods as ShoppingCart, so the StoreService will think it is a shopping cart. However, when the StoreService calls a method of ShoppingCart, the proxy lazily parses it and delegates the call to the real ShoppingCart bean in session scope. Now, with an understanding of this scope, let's discuss the proxyMode property. As shown in the configuration, the proxyMode property is set to ScopedProxyMode.INTERFACES, which indicates that the proxy implements the ShoppingCart interface and delegates the call to the implementing bean.

 

 

This is fine (and the ideal proxy pattern) if ShoppingCart is an interface rather than a class . But if ShoppingCart is a concrete class, Spring has no way to create interface-based proxies. At this point, it must use CGLib to generate class-based proxies. So, if the bean type is a concrete class, we must set the proxyMode property to ScopedProxyMode.TARGET_CLASS to indicate that the proxy is to be created in a way that generates the target class extension. Although I've mostly focused on session scope, request scoped beans face the same wiring issues. So request-scoped beans should also do so in a scoped proxy fashion

 

 

1.2 Declaring scoped proxies in XML

 

If you need to use XML to declare session or request scoped beans, then you cannot use the @Scope annotation and its proxyMode attribute. The scope attribute of the <bean> element can set the scope of the bean, but how do you specify proxy mode?

To set the proxy mode, we need to use a new element of the Spring aop namespace:

<aop:scoped-proxy> is a Spring XML configuration element that does the same thing as . It tells Spring to create a scoped proxy . By default, it uses CGLib to create a proxy for the target class. But we can ask it to generate interface-based proxies by setting the proxy-target-class property to false:

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325097470&siteId=291194637