Analysis of spring source code BeanDefinition

The last chapter said that we want to simulate the Mapper automatic injection of Mybatis, and this automatic injection uses BeanDefinition, so we need to understand this thing first. To understand the code in the next chapter.

In short, it is the modeling object of Bean.
If you have an understanding of Java, you must know a sentence called: everything is an object.
For java, Bean is also an object. Since it is an object, it can be abstracted and stored through a certain structure. Then the abstract structure is BeanDefinition.
BeanDefinition records all the attributes of the Bean object, such as constructor, constructor parameters, basic attributes, singleton, lazy loading, and so on.
BeanDefinition is a public interface in the real use of spring. Several different types of BeanDefinition are implemented in the framework. Let's list a few common attributes for a preliminary understanding.

● ConstructorArgumentValues constructorArgumentValues: if there is a value in this object, spring will fill it as a parameter of the construction method
● String scope = SCOPE_DEFAULT: default singleton
● String[] dependsOn: whether it depends on other bean s
● Object beanClass: the class described by the BeanDefinition
● mutablepropertyvalues: if there is a value in this object, spring will fill it as a setter method

Let's simply talk about the instantiation process of objects: suppose there are N objects on the disk Java files, I will first edit these java files into Class files. After the program starts, the JVM will load the contents of these class files into memory. When the new keyword is encountered, it will be instantiated according to the template information of the class.

However, in the real operation of the Spring framework, the situation is still relatively complex.

  1. Start the Spring container, scan the annotated classes (the annotated classes are to be managed by the Spring container), and store these classes into a collection.
  2. Traverse the collection, parse the object, and generate a BeanDefinition for each class
  3. Store the initialized BeanDefinition into the Map
  4. Call all beanfactoryprocessors (this is an inevitable experience in the Bean life cycle, which will be described in detail later)
  5. Before instantiation, spring will parse and verify the BeanDefinition object to see if the current object needs to be instantiated now.
  6. If everything is normal, continue to follow the process, and an object will be instantiated directly to complete automatic injection, and finally put into the singleton pool for call.
  7. If we implement beanfactoryprocessor ourselves and modify and extend the BeanDefinitionMap, we won't go to Part 6, but step 7 first. as follows
@Component
public class X {
	public void get() {
		System.out.println("X Bean");
	}
}

@Component
public class Y {
	public  void get() {
		System.out.println("Y Bean");
	}
}

public class Z {
	public void get() {
		System.out.println("Z Bean");
	}
}

@Component
public class ZBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		AbstractBeanDefinition x = (AbstractBeanDefinition)beanFactory.getBeanDefinition("x");
		x.setBeanClass(Z.class);
	}
}

	@Test
	public void TestBeanFactory(){
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		context.scan("com.spring.beanFactory");
		context.refresh();
		context.getBean(Y.class).get();
		context.getBean(Z.class).get();
		context.getBean(X.class).get();
	}

//results of enforcement
Y Bean
Z Bean

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.spring.beanFactory.X' available

That is to say, before the object in BeanDefinition is instantiated, we can modify this object, so we can inject Mapper to provide operation space.

Tags: Java Spring source code

Posted by dc_jt on Thu, 14 Apr 2022 08:52:27 +0930