JAVA-6-[Spring Framework] Bean scope and life cycle

1 Spring Bean

1、Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)2、普通bean:在配置文件中定义的bean类型就是返回的类型。
3、工厂bean:在配置文件中定义的bean类型可以和返回类型不一样。
第一步 创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步 实现接口里面的方法,在实现的方法中定义返回的bean类型

1.1 Bean Name Derivation

The objects managed by the Spring IoC container are called beans, and the beans are created according to the information in the Spring configuration file.

You can think of the Spring IoC container as a big factory. Beans are equivalent to the products of the factory. If you want this big factory to produce and manage beans, you need to tell the container which beans are needed and how to assemble the beans.
1. The origin of the name JAVA
When Java was first invented by Sun, it was not called Java, but Oak (oak tree). The name Oak is named after an oak tree outside the office of James Gosling, one of the inventors of Java. It can be seen how casual they were when they named it.
insert image description here

Unfortunately, they soon discovered that the name Oak had already been registered as a trademark by other companies, so they had to create another name. Which name is better? They debated for a long time at the time, and finally chose the name "Java" from several candidate names.

Why did you choose Java as the name? This is to mention what the author often mentions, Westerners like to use food-related content to name. In addition, the brain circuits of these programmers at that time were very strange: the name Java was associated with the hot coffee in the office. Historically, in 1696, when the Dutch colonized Indonesia, coffee seedlings began to spread in Jakarta, the current capital of Indonesia. After that, people frantically planted coffee seedlings in Indonesia and supplied them to Europe. Later, an island called Java in Indonesia was rich in coffee. Because of the reputation of the coffee produced on the island, it is easy to associate the word Java with coffee. Thus, the name of the programming language Java was born.

Interestingly, due to this naming of Java, when Java EE changed its name later, it changed the name to Jakarta EE. Jakarta is now the capital of Indonesia. Therefore, the founders of Jav, who had no blood relationship with Indonesia, used a series of names related to Indonesia.

Also because of this name, many things related to Java have used names related to coffee beans, such as NetBeans, Beans in Spring, etc.
Two, the origin of Bean
insert image description here

Bean is a very basic concept in the Spring framework, and the word bean means "beans" in English. From the actual use of Bean in the Spring framework, the two seem to have nothing to do with each other, so why such a naming?
Bean represents a basic unit in the Spring framework. Almost all preset objects in the Spring framework are a kind of "Bean". Various processing of data is also performed in units of Beans, and user-defined data is also It needs to be built into a bean before it can be processed.

On the one hand, if the bean is named according to its actual meaning in the Spring framework, it should be named after words such as "element" and "unit". But the problem is that words such as "element", "unit", "atom" and "component" have become or may become proper nouns in the field of computer-related fields, if With this naming, there may be "ambiguous" conflicts.

On the other hand, Westerners like to name things after food and drink. "Bean" can also be regarded as a basic ingredient in catering.

1.2 Spring configuration file

Spring configuration files support two formats, XML file format and Properties file format.
(1) The Properties configuration file mainly exists in the form of key-value key-value pairs. It can only assign values ​​and cannot perform other operations. It is suitable for simple property configuration.

(2) The XML configuration file is a tree structure, which is more flexible than the Properties file. The structure of the XML configuration file is clear, but the content is relatively cumbersome, which is suitable for large and complex projects.

1. Normally, Spring's configuration files use XML format .

XML配置文件的根元素是<beans>,该元素包含了多个子元素<bean>。
每一个<bean>元素都定义了一个Bean,
并描述了该Bean如何被装配到Spring容器中。

Two, Beans.xml file example

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="helloWorld123" class="net.biancheng.HelloWorld">
        <property name="message" value="Hello World! Testing" />
    </bean>
</beans>

insert image description here

2 Bean scope

When defining a bean in Spring, you must declare options for the bean's scope. For example, to force Spring to create a new bean instance each time it is needed, you should declare the bean's scope property as prototype. Similarly, if you want Spring to return the same bean instance each time it is needed, you should declare the bean's scope property as singleton.

The Spring framework supports the following five scopes, which are singleton, prototype, request, session and global session. The descriptions of the five scopes are as follows.

Note that three of them are available if you use a web-aware ApplicationContext.
insert image description here

2.1 singleton scope

Singleton is the default scope, that is, when defining a bean, if no scope configuration item is specified, the scope of the bean is defaulted to singleton.
When the scope of a bean is Singleton, there will only be one shared bean instance in the Spring IoC container, and all requests for the bean will only return the same instance of the bean as long as the id matches the bean definition.

That is, when a bean definition is set to singleton scope, the Spring IoC container will only create the only instance of the bean definition.

Singleton is a singleton type, that is, when the container is created, a bean object is automatically created at the same time, whether you use it or not, it exists, and the object obtained every time is the same object. Note that Singleton scope is the default scope in Spring. You can set the scope property to singleton in the bean configuration file, as follows:

<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="singleton">
    <!-- collaborators and configuration for this bean go here -->
</bean>

MainApp.java file

package net.biancheng;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        HelloWorld objA = (HelloWorld) context.getBean("helloWorld123");
        objA.setMessage("I am A");
        objA.getMessage();
        HelloWorld objB = (HelloWorld) context.getBean("helloWorld123");
        objB.getMessage();
    }
}

Output the following information:

Your Message : I'm object A
Your Message : I'm object A

2.2 prototype scope

When the scope of a bean is Prototype, it means that a bean definition corresponds to multiple object instances. Prototype-scoped beans cause a new bean instance to be created each time the bean is requested (by injecting it into another bean, or calling the container's getBean() method programmatically).

Prototype is a prototype type. It is not instantiated when we create a container, but an object is created when we get a bean, and the objects we get every time are not the same object. As a rule of thumb, you should use prototype scope for stateful beans and singleton scope for stateless beans.

To define prototype scope, you can set the scope property to prototype in the bean configuration file, as follows:

<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="prototype">
   <!-- collaborators and configuration for this bean go here -->
</bean>

Beans.xml file

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="helloWorld123" class="net.biancheng.HelloWorld" scope="prototype">
        <property name="message" value="Hello World! Testing" />
    </bean>

</beans>

The output is as follows:

message : I am A
message : Hello World! Testing

3 Bean life cycle

When a bean is instantiated, it may need to perform some initialization to bring it into a usable state. Likewise, when a bean is no longer needed and is removed from the container, some cleanup may be required.

Although there is still some activity that occurs between bean instantiation and destruction, this time only two important lifecycle callback methods are discussed, which are required during bean initialization and destruction.

In order to define the installation and teardown of a bean, we just declare it with init-method or destroy-method parameters.
The init-method attribute specifies a method that is called immediately when the bean is instantiated.
destroy-method specifies a method that can only be invoked after the bean is removed from the container.

Bean life cycle can be expressed as: Bean definition - Bean initialization - Bean use - Bean destruction

4.3.1 Initialization callback

(1) Method 1

通过org.springframework.beans.factory.InitializingBean接口提供下面的方法:
void afterPropertiesSet() throws Exception;
可以简单地实现上述接口和初始化工作可以在afterPropertiesSet()方法中执行,如下所示:
public class ExampleBean implements InitializingBean {
    
    
   public void afterPropertiesSet() {
    
    
      // do some initialization work
   }
}

(2) Method 2

在基于XML的配置元数据的情况下,可以使用init-method属性来指定带有void无参数方法的名称。
例如:
<bean id="exampleBean" class="examples.ExampleBean" init-method="init"/>
下面是类的定义:
public class ExampleBean {
    
    
   public void init() {
    
    
      // do some initialization work
   }
}

4.3.2 Destruction callback

(1) Method 1

org.springframework.beans.factory.DisposableBean 接口提供下面的方法:
void destroy() throws Exception;
因此,可以简单地实现上述接口并且结束工作可以在destroy()方法中执行,如下所示:
public class ExampleBean implements DisposableBean {
    
    
   public void destroy() {
    
    
      // do some destruction work
   }
}

(2) Method 2

在基于XML的配置元数据的情况下,可以使用destroy-method属性来指定带有void无参数方法的名称。例如:
<bean id="exampleBean" class="examples.ExampleBean" destroy-method="destroy"/>
下面是类的定义:
public class ExampleBean {
    
    
   public void destroy() {
    
    
      // do some destruction work
   }
}

Note: If you are using Spring's IoC container in a non-web application environment;
for example in a rich client desktop environment; then you need to register shutdown hooks in the JVM.
Doing so ensures a graceful shutdown by calling the destroy method on individual beans in order for all resources to be released
.

4.3.3 Code example

(1) File HelloWorld.java

package net.biancheng;

public class HelloWorld {
    
    
    private String message;

    public void setMessage(String message) {
    
    
        this.message = message;
    }

    public void getMessage() {
    
    
        System.out.println("message : " + message);
    }

    public void init(){
    
    
        System.out.println("Bean is going through init.");
    }
    public void destroy(){
    
    
        System.out.println("Bean will destroy now.");
    }
}

(2) File MainApp.java
Note: Here, you need to register a registerShutdownHook() method to close the hook declared in the AbstractApplicationContext class. It will ensure a graceful shutdown and call the associated destroy method.

package net.biancheng;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class MainApp {
    
    
    public static void main(String[] args) {
    
    
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        HelloWorld obj = (HelloWorld) context.getBean("helloWorld123");
        obj.getMessage();
        context.registerShutdownHook();
    }
}

(3) File Beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="helloWorld123" class="net.biancheng.HelloWorld"
          init-method="init" destroy-method="destroy">
        <property name="message" value="Hello World! Testing" />
    </bean>

</beans>

Output after running

Bean is going through init.
message : Hello World! Testing
Bean will destroy now.

4.3.4 Default initialization and destruction methods

If you have too many beans with initialization or destruction methods with the same name, then you don't need to declare initialization and destruction methods on each bean.
The framework provides flexibility to configure this situation using the default-init-method and default-destroy-method attributes on the element, as follows:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
    default-init-method="init" 
    default-destroy-method="destroy">

   <bean id="..." class="...">
       <!-- collaborators and configuration for this bean go here -->
   </bean>

</beans>

4.4 Post Processor

Bean post-processors allow additional processing of beans before and after invocations of initialization methods.
​The BeanPostProcessor interface defines a callback method, which can be implemented to provide its own instantiation logic, dependency parsing logic, etc. It is also possible to implement some custom logic callback methods after the ​Spring​ container completes instantiation, configuration and initialization of a ​bean by inserting one or more ​BeanPostProcessor​ implementations.

Multiple ​BeanPostProcessor​interfaces can be configured, and the execution order of these ​BeanPostProcessor​interfaces can be controlled by setting the ​order​property provided by the ​Ordered interface implemented by BeanPostProcessor.

​BeanPostProcessor​ can operate on ​bean​ (or object) instances, which means that the Spring IoC​container instantiates a ​bean​instance, and the ​BeanPostProcessor​interfaces do their work.

Note:
The ApplicationContext will automatically detect beans defined by implementations of the BeanPostProcessor interface, register these beans as post-processors, and then invoke it at the appropriate time by creating the bean in the container.

In your custom ​BeanPostProcessor​interface implementation class, you need to implement the following two abstract methods ​BeanPostProcessor.postProcessBeforeInitialization(Object, String)​and ​BeanPostProcessor.postProcessAfterInitialization(Object, String)​, pay attention to the accurate naming.

Otherwise, errors such as: " The type InitHelloWorld must implement the inherited abstract method BeanPostProcessor.postProcessBeforeInitialization(Object, String) "​will appear.
(1) File HelloWorld.java

package net.biancheng;

public class HelloWorld {
    
    
    private String message;

    public void setMessage(String message) {
    
    
        this.message = message;
    }

    public void getMessage() {
    
    
        System.out.println("message : " + message);
    }

    public void init(){
    
    
        System.out.println("Bean is going through init.");
    }
    public void destroy(){
    
    
        System.out.println("Bean will destroy now.");
    }
}

(2) The file InitHelloWorld.java
This is a very simple example of implementing a BeanPostProcessor, which enters the name of the bean before and after the initialization of any bean . You can implement more complex logic before and after initialization of the bean, since you have two methods of accessing the post-handler of the built-in bean object.

package net.biancheng;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;
public class InitHelloWorld implements BeanPostProcessor {
    
    
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("BeforeInitialization : " + beanName);
        return bean;  // you can return any other object as well
    }
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("AfterInitialization : " + beanName);
        return bean;  // you can return any other object as well
    }
}

(3) File MainApp.java
Note: Here, you need to register a registerShutdownHook() method to close the hook declared in the AbstractApplicationContext class. It will ensure a graceful shutdown and call the associated destroy method.

package net.biancheng;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class MainApp {
    
    
    public static void main(String[] args) {
    
    
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        HelloWorld obj = (HelloWorld) context.getBean("helloWorld123");
        obj.getMessage();
        context.registerShutdownHook();
    }
}

(4) File Beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="helloWorld123" class="net.biancheng.HelloWorld"
          init-method="init" destroy-method="destroy">
        <property name="message" value="Hello World! Testing" />
    </bean>
    <bean class="net.biancheng.InitHelloWorld" />
</beans>

Output after running

BeforeInitialization : helloWorld123
Bean is going through init.
AfterInitialization : helloWorld123
message : Hello World! Testing
Bean will destroy now.

4.5 Defining Inheritance

A bean definition can contain a lot of configuration information, including constructor parameters, property values, container-specific information such as initialization methods, static factory method names, and so on.

Child bean definitions inherit the configuration data defined by the parent. Subdefinitions can override some values, or add others, as needed.

The inheritance of Spring Bean definitions has nothing to do with the inheritance of Java classes, but the concept of inheritance is the same. You can define a parent bean definition as a template and other child beans can inherit the required configuration from the parent bean.

When you use XML-based configuration metadata, you indicate the definition of a child bean by using the parent property, specifying the parent bean as the property's value.

Guess you like

Origin blog.csdn.net/qq_20466211/article/details/129653982