SpringBean works

In the Spring, the body that make up the application and by the Spring IOC container managed objects, called bean. Simply put, bean that is, assembly and management of objects, in addition, bean there is no difference by IOC container initialization and other objects in the application. While the bean, and the dependencies between each other bean configuration will be described by the metadata.

In Spring bean default is a single case, these singleton Bean how to ensure the security thread in a multithreaded program it?  For example, after the Web applications, Web container for each user request to create a separate Sevlet threads to handle requests, the introduction of the Spring framework, each Action is a singleton, then for Spring-managed Singleton Service Bean, how ensure its security? Spring single embodiment is based BeanFactory Spring container, Bean single embodiment within this container is only one, Java is based on the JVM singleton, only one instance of each JVM.

2 | 0 bean scopes

 

Create a bean definition, and its essence is to create a true example of using the bean definition of class "recipe." The bean definition of a recipe is important, it is very similar to the class, only you can create multiple instances based on a "prescription." You can control not only the various dependencies and configuration values ​​objects can also control the scope of the object. This allows the flexibility to choose the scope of built objects without having to define the scope of the Java Class level. Spring Framework supports five scopes, are set forth in the following table.

Five kinds of scope, Request, the session  , and  global session  three kinds of scopes only use (do not care what you have adopted is a web application framework) in web-based applications, it can only be used in web-based Spring ApplicationContext environment.

Example 1. singleton-- unique bean

When a bean scope of singleton, then Spring IoC container exists only a shared bean instances, and all requests for the bean, as long as the id matching that bean definition will return the same instance of the bean.  singleton is a singleton type (corresponding to a singleton), that is, when you create from a container on and automatically creates an object bean, regardless of whether you're using, but we can specify Bean node  lazy-init=”true” to delay the initialization bean, this time only initialized when the first gets the bean will be initialized bean, that is, the first request of the bean. Every time the acquired objects are the same object. Note, singleton scope is the default scope in Spring. To define a singleton in XML bean, may be configured such that:

<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">

Can also  @Scope annotation (which can display scope designated bean.) Manner

@Service @Scope("singleton") public class ServiceImpl{ }

2. prototype-- every request to create a new bean instance

When a bean scope of prototype, showing a plurality of bean definition object instances.  prototype scope bean bean result in each of the request (() method which is injected into another bean, or in a manner getBean program calls the container will create a new instance when bean). prototype is a prototype type, it does not instantiated when we create the container, but when we get the bean when it will go to create an object, and every time we get to the target is not the same object. According to experience, for stateful bean should use the prototype scope, and to stateless bean should use the singleton scope.  Bean defined in XML prototype, may be configured such that:

<bean id= "account" class="com.foo.DefaultAccount" scope="prototype"/> 或者 <bean id="account" class="com.foo.DefaultAccount" singleton="false"/>

By  @Scope Implementation Notes ways do not demonstrate.

3. request-- every HTTP request will generate a new bean, which is only valid in the current HTTP request

request applies only to the Web program, every HTTP request will generate a new bean, while the bean is only valid for the current HTTP request, after the end of the request, the life cycle of the object ends.  Bean defined in XML request, can be configured such that:

<bean id= "loginAction" class=cn.csdn.LoginAction" scope="request"/>

4. session-- every HTTP request will generate a new bean, which is only valid in the current HTTP session

session only applies to Web applications, session scope means that for every created instance of HTTP request will generate a new bean, while the bean is only valid within the current HTTP session. As with the request scope, you can rest assured that changes as needed the internal state, while other HTTP session according to an example userPreferences created will not see these changes in a specific state of the HTTP session. When the HTTP session was eventually abandoned when, bean in the scope of HTTP session will also be discarded.

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

5. globalSession

global session scope is similar to standard HTTP session scope, but only in the portlet web-based application makes sense. Portlet Specification defines the concept of global Session, it is all a single portlet web application constitute various different portle t shared. In the scope defined global session bean is defined within the scope of the life cycle of the global portlet Session.

<bean id="user" class="com.foo.Preferences "scope="globalSession"/>

3 | 0 bean life cycle


Spring Bean is the most important part of the Spring applications. So take a look at the Spring container in a bean initialization time will do those things, the order is how, in the container is closed, what things will be done.

spring version: 4.2.3.RELEASE
view of the Spring source code is gradle built, I decided to abandon my big maven, try the next Hong Ju had recommended gradle. Junit test run under beanLifeCycle module can see the following output in the console, you can clearly understand the Spring container to create, initialize and destroy Bean's time to do those things in order.

Spring ===================================== call initialization container GiraffeService no argument constructor set utilized GiraffeService set the property value method call setBeanName :: bean Name defined in context = giraffeService call setBeanClassLoader, ClassLoader Name = sun.misc.Launcher $ AppClassLoader call setBeanFactory, setBeanFactory :: giraffe bean singleton = true calling setEnvironment call setResourceLoader :: Resource File Name = spring -beans.xml call setApplicationEventPublisherCall setApplicationContext :: Bean Definition Names = [giraffeService , org.springframework.context.annotation.CommonAnnotationBeanPostProcessor # 0, com.giraffe.spring.service.GiraffeServicePostProcessor # 0] BeanPostProcessor method of execution postProcessBeforeInitialization, beanName = giraffeService call the method PostConstruct comment marked postProcessAfterInitialization interface method performed InitializingBean afterPropertiesSet method for performing configuration of init-method BeanPostProcessor performed, the beanName = giraffeService the Spring container initialized ========================= ============ acquired from the container Bean giraffe Name = Lee Guangzhu ============================= ======== calling method performed preDestroy annotation labels destroy method performed DisposableBean interface configured destroy-method Spring container is closed

Let's look, Spring might do something lifecycle from creation to destruction in the Bean.

initialization 和 destroy

Sometimes we need good after Bean and Bean destruction of property value set to do something before, such as checking whether a property Bean in a normal set of values. The Spring Framework provides a variety of ways so that we can perform initialization and pre-destroy methods in Spring Bean's life cycle.

1. To achieve InitializingBean and DisposableBean Interface

These two interfaces comprise only one way. () Method by implementing the interface InitializingBean afterPropertiesSet would do something after the Bean property value is set to achieve DisposableBean interface destroy () method can do some operations before destroying Bean.

Examples are as follows:

public class GiraffeService implements InitializingBean,DisposableBean { @Override public void afterPropertiesSet() throws Exception { System.out.println("执行InitializingBean接口的afterPropertiesSet方法"); } @Override public void destroy() throws Exception { System.out.println("执行DisposableBean接口的destroy方法"); } }

This method is simple, but not recommended. Because such a framework the coupling will be realized and Bean Spring together.

2. Specify the init-method and destroy-method methods bean configuration file

Spring allows us to create your own init method and destroy method, as long as the specified value and the destroy-method in Bean-method init configuration file can perform a number of operations before Bean initialization and destruction.

Examples are as follows:

public class GiraffeService { // by <bean> the destroy-method property specifies a method to destroy public void and destroyMethod () throws Exception {System.out.println ( "configuration performed destroy-method");} // by <bean> the init-method property specifies the method of initialization public void the initMethod () throws Exception {System.out.println ( "perform configuration init-method");}}

Profile configuration:

<bean name="giraffeService" class="com.giraffe.spring.service.GiraffeService" init-method="initMethod" destroy-method="destroyMethod"> </bean>

Note that since the init-method and post-method defined method may throw an exception but can not have parameters.

In this way more recommended, because you can create your own method, without having to depend directly on the Bean implementation of the framework spring.

3. Use @PostConstruct and @PreDestroy comment

In addition to the way xml configuration, Spring also supports the use  @PostConstructand  @PreDestroyannotations to specify  init and  destroy methods. These two notes are in the javax.annotation package. In order to comment may take effect, you need to define org.springframework.context.annotation.CommonAnnotationBeanPostProcessor in the configuration file or context: annotation-config

Examples are as follows:

public class GiraffeService { @PostConstruct public void initPostConstruct () {System.out.println ( "PostConstruct annotations perform the method marked");} @PreDestroy public void preDestroy () {System.out.println ( "labels annotated to perform the method preDestroy ");}}

Profiles:

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />

* Aware interfaces to achieve some of the objects using the Spring framework in the Bean

Sometimes we need to perform some operations use the Spring Framework Bean Initialization in some of its objects, get some parameters such as the ServletContext, get the name of ApplicaitionContext BeanDefinition in obtaining Bean name in the container and so on. To make Bean can get to some of its own object framework, Spring provides a set of interfaces called * Aware of.

These interfaces are inherited org.springframework.beans.factory.Awaremarker interface, and provides a set * The method implemented by Bean, Spring objects through the corresponding setter-based dependency injection method can be used Bean.
Online said, these interfaces are implemented using the observer pattern, similar to the servlet listeners, it is not yet clear, but it is not within the scope of this article to discuss.
Describes some important Aware Interface:

  • ApplicationContextAware : get ApplicationContext object that can be used to get the names of all of the Bean definition.
  • The BeanFactoryAware : obtaining BeanFactory object that can be used to detect Bean scopes.
  • BeanNameAware : get the name of Bean defined in the configuration file.
  • The ResourceLoaderAware : get ResourceLoader object, you can obtain a file in the classpath.
  • ServletContextAware : ServletContext object can be obtained in a MVC application, the parameters can be read in context.
  • ServletConfigAware : ServletConfig object can be obtained in a MVC application, config parameter can be read.
public class GiraffeService implements ApplicationContextAware, ApplicationEventPublisherAware, BeanClassLoaderAware, BeanFactoryAware, BeanNameAware, EnvironmentAware, ImportAware, ResourceLoaderAware{ @Override public void setBeanClassLoader(ClassLoader classLoader) { System.out.println("执行setBeanClassLoader,ClassLoader Name = " + classLoader.getClass().getName()); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("执行setBeanFactory,setBeanFactory:: giraffe bean singleton=" + beanFactory.isSingleton("giraffeService")); } @Override public void setBeanName(String s) { System.out.println("执行setBeanName:: Bean Name defined in context=" + s); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("执行setApplicationContext:: Bean Definition Names=" + Arrays.toString(applicationContext.getBeanDefinitionNames())); } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { System.out.println("执行setApplicationEventPublisher"); } @Override public void setEnvironment(Environment environment) { System.out.println("执行setEnvironment"); } @Override public void setResourceLoader(ResourceLoader resourceLoader) { Resource resource = resourceLoader.getResource("classpath:spring-beans.xml"); System.out.println("执行setResourceLoader:: Resource File Name=" + resource.getFilename()); } @Override public void setImportMetadata(AnnotationMetadata annotationMetadata) { System.out.println("执行setImportMetadata"); } }

BeanPostProcessor

* Aware interfaces above is a process for the realization of these custom interfaces Bean initialization,
the Spring Bean can also be a container for all, or some Bean custom initialization process, just to provide a class that implements the interface can BeanPostProcessor. The interface contains two methods, postProcessBeforeInitialization and postProcessAfterInitialization. postProcessBeforeInitialization Bean method will be executed before the initialization container, postProcessAfterInitialization Bean method is performed after the initialization container.

Examples are as follows:

public class CustomerBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("执行BeanPostProcessor的postProcessBeforeInitialization方法,beanName=" + beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("执行BeanPostProcessor的postProcessAfterInitialization方法,beanName=" + beanName); return bean; } }

To BeanPostProcessor Bean of Bean Like other as defined in the configuration file

<bean class="com.giraffe.spring.service.CustomerBeanPostProcessor"/>

to sum up

and so. . . Combined with the contents of the first console output, Spring Bean's life cycle is this paper:

  • Bean container configuration file find the definition in the Spring Bean.
  • Bean Bean container creates an instance of the use of Java Reflection API.
  • If the attribute value relates to the use of some method of setting attributes of a set.
  • If the Bean implements BeanNameAware interfaces, call setBeanName () method, passing in the name of Bean.
  • If the Bean implements BeanClassLoaderAware interfaces, call setBeanClassLoader () method, passing in the instance of ClassLoader object.
  • If the Bean implements BeanFactoryAware interfaces, call setBeanClassLoader () method, passing in the instance of ClassLoader object.
  • Similar to the above, if the implementation of the other * Aware interfaces, call the appropriate method.
  • If you have and load the Bean Spring container BeanPostProcessor related objects, perform postProcessBeforeInitialization () method
  • If the Bean implements InitializingBean interfaces, perform afterPropertiesSet () method.
  • If the Bean is defined in the configuration file contains the init-method attribute, the specified method.
  • If you have and load the Bean Spring container BeanPostProcessor related objects, perform postProcessAfterInitialization () method
  • When you want to destroy the Bean, Bean realized if DisposableBean interfaces, execute destroy () method.
  • When Bean to be destroyed, if Bean is defined in the configuration file contains the destroy-method attribute, the specified method.

Represented in Fig bit (Figure Source: http: //www.jianshu.com/p/d00539babca5):

By comparison similar to the Chinese version:

In fact, many times we do not really implement those interfaces described above, say, here we remove those interfaces for bean singleton and non-singleton bean to describe the next life cycle:

Singleton object management

When the scope = "singleton", i.e. default, instantiates (i.e., instantiation container) when the starting container. But we can specify Bean node lazy-init = "true" to delay the initialization bean, this time, only the first acquisition will be initialized when the bean bean, the bean that is initialized when the first request. As follows:

<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" lazy-init="true"/>

To all singleton bean default initialization delay are applied, may be provided in the root node beans default-lazy-init property is true, as follows:

<beans default-lazy-init="true" …>

By default, Spring reading xml file, it will create the object. When creating an object first call the constructor, then call the method init-method attribute value specified. When an object is destroyed, destroy-method calls the method specified in the attribute value (e.g., call Container.destroy () method of the time). Write a test class, as follows:

public class LifeBean { private String name; public LifeBean(){ System.out.println("LifeBean()构造函数"); } public String getName() { return name; } public void setName(String name) { System.out.println("setName()"); this.name = name; } public void init(){ System.out.println("this is init of lifeBean"); } public void destory(){ System.out.println("this is destory of lifeBean " + this); } }

 life.xml配置如下:

<bean id="life_singleton" class="com.bean.LifeBean" scope="singleton" init-method="init" destroy-method="destory" lazy-init="true"/>

测试代码:

public class LifeTest { @Test public void test() { AbstractApplicationContext container = new ClassPathXmlApplicationContext("life.xml"); LifeBean life1 = (LifeBean)container.getBean("life"); System.out.println(life1); container.close(); } }

运行结果:

LifeBean()构造函数 this is init of lifeBean com.bean.LifeBean@573f2bb1 …… this is destory of lifeBean com.bean.LifeBean@573f2bb1

非单例管理的对象

scope=”prototype”时,容器也会延迟初始化 bean,Spring 读取xml 文件的时候,并不会立刻创建对象,而是在第一次请求该 bean 时才初始化(如调用getBean方法时)。在第一次请求每一个 prototype 的bean 时,Spring容器都会调用其构造器创建这个对象,然后调用init-method属性值中所指定的方法。对象销毁的时候,Spring 容器不会帮我们调用任何方法,因为是非单例,这个类型的对象有很多个,Spring容器一旦把这个对象交给你之后,就不再管理这个对象了。

为了测试prototype bean的生命周期life.xml配置如下:

<bean id="life_prototype" class="com.bean.LifeBean" scope="prototype" init-method="init" destroy-method="destory"/>

测试程序:

public class LifeTest { @Test public void test() { AbstractApplicationContext container = new ClassPathXmlApplicationContext("life.xml"); LifeBean life1 = (LifeBean)container.getBean("life_singleton"); System.out.println(life1); LifeBean life3 = (LifeBean)container.getBean("life_prototype"); System.out.println(life3); container.close(); } }

运行结果:

LifeBean()构造函数 this is init of lifeBean com.bean.LifeBean@573f2bb1 LifeBean()构造函数 this is init of lifeBean com.bean.LifeBean@5ae9a829 …… this is destory of lifeBean com.bean.LifeBean@573f2bb1

可以发现,对于作用域为 prototype 的 bean ,其destroy方法并没有被调用。如果 bean 的 scope 设为prototype时,当容器关闭时,destroy 方法不会被调用。对于 prototype 作用域的 bean,有一点非常重要,那就是 Spring不能对一个 prototype bean 的整个生命周期负责:容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。 不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法。但对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责(让Spring容器释放被prototype作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用)。谈及prototype作用域的bean时,在某些方面你可以将Spring容器的角色看作是Java new操作的替代者,任何迟于该时间点的生命周期事宜都得交由客户端来处理。

Spring 容器可以管理 singleton 作用域下 bean 的生命周期,在此作用域下,Spring 能够精确地知道bean何时被创建,何时初始化完成,以及何时被销毁。而对于 prototype 作用域的bean,Spring只负责创建,当容器创建了 bean 的实例后,bean 的实例就交给了客户端的代码管理,Spring容器将不再跟踪其生命周期,并且不会管理那些被配置成prototype作用域的bean的生命周期

Guess you like

Origin www.cnblogs.com/long-ke/p/11277111.html