Bean object in Spring IOC

Bean object in Spring IOC

(1) What is Bean

Suddenly I found out that Bean was mentioned many times, and I forgot to talk about Bean. It's okay, it's not too late to talk about it now. Bean in Java is a kind of specification and a special kind of java. So let's take a look at the Bean specification first.

  1. Bean must generate public class.
  2. All attributes must be encapsulated, and the attributes of the Bean class are private.
  3. The attribute value should be accessed and modified through a set of methods (getXxx and setXxx).
  4. The Bean class must have an empty constructor (default constructor).

These are the basic specifications of Bean, we can expand, but these most basic are to be satisfied, otherwise it will not be regarded as a standard Bean. Let me give an example of a standard Bean, pay attention to the above four elements.

public class User {
    
    
    private String id;
    private String name;

    public User(){
    
    }

    public User(String id, String name) {
    
    
        this.id = id;
        this.name = name;
    }

    public String getId() {
    
    
        return id;
    }

    public void setId(String id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }
}

Yes, Bean is such a special class, this thing must be kept in mind, because it will be used frequently later.

(2) Three construction methods of Bean object

Since we have spring, we don't need to worry about the construction of objects anymore, just leave everything to spring. However, no matter how advanced the framework is, the bottom layer of it is still doing some very simple things. We may often do it ourselves in the past. Therefore, to learn Spring, we must know what it is and why it is. Let's take a look at the ways to construct Bean objects. By the way, understand what their principle is.

1. Construction method

This is the construction method we use most. You must be very curious. In the previous case, why did we write a sentence in the configuration file:

<bean id="circle" class="com.demo.Circle"/>

Then this Bean object is constructed by spring and put into the IOC container? In fact, this thing is nothing tall, in fact, spring uses reflection to call the default constructor of this class. It's that simple.

So the question is, if we have attributes in our object (for the time being assume that attributes only contain basic types and String, object attributes will be discussed later), how should we construct it? How to write this configuration file? Very simple, each Bean object has a setter method (if you don't remember, you can review the structure of the Bean written above). The framework can pass the required value to the property by calling the setter method. This is property injection. For example, we try to construct a Bean object mentioned at the beginning of this article:

<bean id="user" class="com.beans.User">
	<property name="id" value="666"></property>
    <property name="name" value="666"></property>
</bean>

What is the main purpose of this configuration? First, as usual, call the default constructor to construct an object, and then call two setter methods to assign values ​​to two properties. This is the case with traditional code:

User user = new User();
user.setId("666");
user.setName("666");

Of course, we rarely do this ourselves. If we need to assign a value to a property, we can directly override the construction method. By passing parameters, we can directly assign a value to the property while creating the object, which can reduce the amount of code. Let's take a look at how to make the framework call the Bean's parameterized construction method:

<bean id="user" class="com.beans.User" >
	<constructor-arg name="id" value="666"></constructor-arg>
    <constructor-arg name="name" value="666"></constructor-arg>
</bean>

This configuration is equivalent to directly calling the parameterized construction method, where arg is the abbreviation of argument (parameter), so constructor-arg means the parameter list of the construction method, name is obviously the parameter name, and value is ours The parameter value to be filled in. So we have to fill in all the parameters in the parameter list, just like we did in the past:

User user = new User("666", "666");

Now you should have an idea of ​​what the spring framework does. What seems to be a tall framework is nothing more than that. The most basic things will never escape.

2. Static factory structure

This method is generally only used in specific scenarios, so let's just take a look. The static factory here is similar to the factory model we talked about earlier. First, we need to have a factory:

public class UserFactory {
    
    
    public static User createPerson(){
    
    
        return new User();
    }
    public static User createPerson(Integer id,String name){
    
    
        return new User(id,name);
    }
}

Let's take a look at how to write the configuration file:

<bean id="user" class="com.beans.factory.UserFactory" factory-method="createPerson">
    <constructor-arg name="id" value="666"></constructor-arg>
    <constructor-arg name="name" value="666"></constructor-arg>
</bean>

To use the static factory method to create a Bean instance, you need to specify the following attributes for the <bean /> element in addition to id:

  1. class: Specify the full class name of the static factory (equivalent to the address of the specified factory)
  2. factory-method: Specify which method of the static factory creates the Bean instance (specify which workshop of the factory creates the Bean)
  3. Method parameters: If the static factory method requires parameters, use the <constructor-arg /> element to pass in.

3. Example factory structure

The only difference between an instance factory and a static factory is that we need to instantiate the factory object before we can construct the Bean object we need:

<!-- 先构造工厂对象,class指定该工厂的实现类,工厂对象负责产生其他Bean实例 --> 
<bean id="userFactory" class="com.beans.factory.UserFactory"/> 

<!-- 再引用工厂对象来配置其他Bean -->
<bean id="user" factory-bean="userFactory" factory-method="createPerson">
    <constructor-arg name="id" value="666"></constructor-arg>
	<constructor-arg name="name" value="666"></constructor-arg>
</bean>

To call the instantiation factory, you need to specify the following attributes for <bean /> in addition to id:

  1. factory-bean: This attribute specifies the id of the factory bean
  2. factory-method: This attribute specifies the factory method of the instance factory.
  3. Method parameters: If the static factory method requires parameters, use the <constructor-arg /> element to pass in.

Instance factories and static factories are not used very much in normal times. The most used construction method in normal development is the construction method mentioned at the beginning. Now there is an important question, what if the attribute of the Bean object is an object? This is what we are going to talk about next-dependency injection (DI)

(Three) dependency injection

Speaking of spring IOC, we have to talk about DI. These two things are basically complementary to each other, so we will look at the relationship between IOC and DI. Inversion of Control-IOC (Inversion of Control) means the transfer of control of the created object. In the past, the initiative and timing of creating objects were controlled by yourself, but now this power is transferred to spring.

One of the most important functions of IOC is to dynamically provide an object with other objects it needs as attributes during system operation. This is achieved through DI (Dependency Injection). Let me give an example of dependency injection:

For example, Class A needs to use JBDC. Previously, we had to write code in Class A to create a new Connection object ourselves (here we don't consider the database connection pool). Now with spring, we only need to use the configuration file to tell spring that a Connection object is needed in class A. As for how and when this Connection is constructed, class A does not need to know. At runtime, Spring will construct a Connection object at an appropriate time, and then inject it into Class A, thus completing the control of the relationship between each object. Class A needs to rely on the Connection property to run normally, and this Connection object is injected into A by spring, so the name of dependency injection comes from.

After reading so much, did you find that dependency injection and the attribute injection we mentioned above are actually the same kind of things, and they both dynamically assign values ​​to the attributes of the object, but the attribute here is an object, the attribute mentioned above It's a simple type. Dependency injection sounds very high-end, but it is actually just assigning values ​​to object properties.

(4) Bean's life cycle

I talked about how to write a configuration file, so you must be curious about what the state of this Bean should look like in spring at all times. So let's take a look at the life cycle of Bean in spring. However, there is one point to be explained in advance. Spring only helps us manage the complete life cycle of singleton beans. For multi-prototype beans, Spring will not manage the follow-up after it is created and handed over to the user. Life cycle. Singleton mode and multiple mode are discussed later.

Insert picture description here
Let's see how our Bean object is generated. This picture looks very scary at first glance. In fact, many of the things in it are extension points, which are interspersed in the life cycle of the Bean. We don't need to toss these extension points at first. Our focus should be on the life cycle of the Bean itself.

In fact, there are only four stages in the life cycle of Bean, which are:

Instantiation
property assignment Populate
initialization Initialization
destruction Destruction

To thoroughly understand Spring's life cycle, we must first keep these four stages in mind. Instantiation and attribute assignment correspond to the injection of the construction method and the setter method. Initialization and destruction are the two stages that users can customize and expand. We can write the logic we need in these two functions. The various expansion points interspersed between these four stages will be discussed later.

First of all, let's look at the first three. Their main logic is in the doCreateBean method. The three methods are called in sequence. These three methods correspond to the three life cycle stages:

//PS:下面的代码已经删去暂时不用了解的部分,只留下核心部分
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {
    
    
   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (instanceWrapper == null) {
    
    
       // 实例化
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
    
    
       // 属性赋值
      populateBean(beanName, mbd, instanceWrapper);
       // 初始化
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
}

With these three, plus one destruction, constitute the four most important life cycle stages of Bean. As shown in the figure below, of course, in addition to these four basic life cycle stages, the figure below also adds some extension points:
Insert picture description here

At the beginning, we only need to know the existence of these extension points. As for how to use them, we will talk about them when we use them later. What we need to understand here are the four most basic life cycles. Other extension points are rarely used in normal development, but when reading some Java middleware source code, these extension points must be understood.

May 11, 2020

Guess you like

Origin blog.csdn.net/weixin_43907422/article/details/105966366