[Spring source code analysis] SpringIOC (1) - Bean and BeanDefinition

A global view of core interfaces and classes

Solve the key problem: turn the relationship between objects to use configuration to manage

  • Dependency Injection - Dependencies are managed in Spring's loC container

  • By wrapping objects in beans to manage objects and perform additional operations

Bean与BeanDefinition

Beans are first-class citizens of Spring:

  • The essence of Bean is a java object, but the life cycle of this object is managed by the container
  • There is no need to add any additional restrictions on the original java class in order to create a bean
  • The control method of java objects is reflected in the configuration

BeanDefinition is the definition of a bean

According to the configuration, the BeanDefinition used to describe the Bean is generated. The common attributes are as follows:

JDK uses java.lang.class to describe this object, and spring uses BeanDefinition to describe beans

  • scope scope( @Scope)
  • Lazy loading lazy-init( @Lazy): Determines whether the Bean instance is lazy loaded
  • preferred primary( @Primary): A bean set to true will be the preferred implementation class
    • When an interface corresponds to multiple implementation beans, the interface using this annotation will be implemented first
  • factory-bean and factory-method ( @Configurationand @Bean)

Demonstration of bean creation with no parameter constructor:
create an entity package in the project and create a User class

package com.wjw.entity;

public class User {
    
    

}

At this point, defining the corresponding bean in xml can be achieved by using the no-parameter construction method

<bean id="user1" class="com.wjw.entity.User" scope="singleton" lazy-init="true" primary="true"/>

Create a bean demo using a static factory:
create another static factory class

package com.wjw.entity.factory;

import com.wjw.entity.User;

public class StaticFactory {
    
    

   public static User getUser(){
    
    
      return new User();
   }
}

At this point, defining the corresponding bean in xml can use the static factory method to achieve

<!-- class的值不是写User对象的全路径,而是写静态工厂的全路径 -->
<!-- factory-method的值写要调用的方法 -->
<bean id="user2" class="com.wjw.entity.factory.StaticFactory" factory-method="getUser" scope="singleton"/>

Example of creating a bean using an instance factory:

package com.wjw.entity.factory;

import com.wjw.entity.User;

public class UserFactory {
    
    

   public User getUser(){
    
    
      return new User();
   }
}

Since the method is not static, it cannot be called directly. You can only create an object of the factory first, and then call it through the object.

<!-- 需要先创建factoryBean对象,再通过factoryBean对象进行调用 -->
<bean id="userFactory" class="com.wjw.entity.factory.UserFactory"/>
<bean id="user3" factory-bean="userFactory" factory-method="getUser" scope="singleton" />

test:

package com.wjw;

import com.wjw.controller.WelcomeController;
import com.wjw.entity.User;
import com.wjw.service.WelcomeService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.FileSystemXmlApplicationContext;

@Configuration
@ComponentScan("com.wjw")
public class Entrance {
    
    

   public static void main(String[] args) {
    
    
      System.out.println("Hello World!");
      String xmlPath = "F:\\Java\\spring-framework-5.2.0.RELEASE\\springdemo\\src\\main\\resources\\spring\\spring-config.xml";
      ApplicationContext applicationContext = new FileSystemXmlApplicationContext(xmlPath);
      WelcomeService welcomeService = (WelcomeService) applicationContext.getBean("welcomeService");
      welcomeService.sayHello("强大的spring框架");

      //得到无参构造函数创建的对象:
      User user1a = (User) applicationContext.getBean("user1");
      User user1b = (User) applicationContext.getBean("user1");
      //得到静态工厂创建的对象:
      User user2a = (User) applicationContext.getBean("user2");
      User user2c = (User) applicationContext.getBean("user2");
      //得到实例工厂创建的对象:
      User user3a = (User) applicationContext.getBean("user3");
      User user3b = (User) applicationContext.getBean("user3");


      System.out.println("无参构造函数创建的对象:" + user1a);
      System.out.println("无参构造函数创建的对象:" + user1b);
      System.out.println("静态工厂创建的对象:" + user2a);
      System.out.println("静态工厂创建的对象:" + user2c);
      System.out.println("实例工厂创建的对象:" + user3a);
      System.out.println("实例工厂创建的对象:" + user3b);
   }
}

Please add image description

What container initialization mainly does (main context)

Please add image description

BeanDefinition source code

Please add image description
Please add image description
Inheriting two interfaces, spring is full of a large number of interfaces, inheriting an interface means having a certain function.

  • AttributeAccessorDefines the most basic way of modifying or obtaining the metadata of any object. It is mainly used here to obtain the attributes of BeanDefinition and operate these attributes.

  • BeanMetadataElementIt mainly defines a getSourcemethod to return a configurable source object, which is mainly used here to return the BeanDefinition object itself.

  • AttributeAccessorSupportYes AttributeAccessorimplementation class.

  • AbstractBeanDefinitionIt is the base class of the BeanDefinition implementation class. It defines some constructors for initializing common properties, corresponding getters and setters, and some common methods for operations. AbstractBeanDefinitionSpring implements some special-purpose BeanDefinitions based on abstract classes.

  • RootBeanDefinitionIt can be used as a BeanDefinition alone, or as a parent class of other BeanDefinitions, but not as other subclasses. (It is usually used to receive the information that multiple BeanDefinitions are combined at runtime. It can receive multiple BeanDefinitions with inheritance relationships, and inherit their combined properties except the parent property). Under normal circumstances, the bean tag in the configuration file will be parsed into RootBeanDefinition, but after spring 2.5, it is used GenericBeanDefinitioninstead, but because of the previous foundation, it will still be RootBeanDefinitionused to .

Please add image description
ps: Inheritance in spring is determined by setting the parent property, not extends

  • ChildBeanDefinitionhas been replaced.
  • GenericBeanDefinition(Bean file configuration attribute definition class) In addition to the BeanDefinition attribute, there is also the parent attribute, which is convenient for setting the parent BeanDefinition when the program is running, and no exception is reported, which is a better solution.

Guess you like

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