The IOC container

The main responsibilities of the IOC container are:

  • Spring IOC can parse these Java objects from configuration files or annotations, depending on the definition of each BeanBeanDefinition, and finally register with the IOC container
  • Dependency Injection (DI), an object can be constructed using constructors, static factory methods, and factory methods. Used in Controller for daily development@AutowiredInjecting a Service is the process of dependency injection.
  • Managing the life cycle of beans, Spring can manage information about beans’ scope, load timing, and so on.
  • In everyday use,ApplicationContextThe interface represents the Spring IOC container

The overview diagram of the container on the Official website of Spring, the configuration of business Java objects plus metadata, is read, parsed by Spring IOC, registered in the IOC container, and made available to the outside world.

Bean

  • The Java objects managed by the Spring IOC container are called beans
  • Beans are essentially Java objects, but on top of that, IOC is responsible for the life cycle of that Java object.
  • In addition to the Java object content itself, Spring provides a series of configuration items that make it easier for developers to define beans. For example, if you want a configuration item to be a singleton, you can configure it in XMLscope="singleton"
  • A named Bean can specify an ID or name in the XML, or if not, it is generated by default as a lowercase hump
  • Alias: In addition to name, you can specify the Bean alias, that is, you can get the Bean from the container by another name.
  1. PersonFactory
@Component
public class PersonFactory {

	/** * this Bean can be personC or Kobe */
	@Bean({"personC", "Kobe"})
	public Person getPerson(a) {
		return new Person("I am Kobe who created by PersonFactory"); }}Copy the code
  1. Demo
@Configuration
@ComponentScan(value = "com.xjm")
public class BeanDefinitionDemoByAnnotation {
	public static void main(String[] args) {
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationContextDemo.class);
		Person kobe = (Person) applicationContext.getBean("Kobe"); System.out.println(kobe.toString()); }}Copy the code

BeanDefinition

According to the configuration, the BeanDefinition is used to describe the Bean. It is an interface that defines some methods that the Bean should have, and lets the lower implementation classes implement these functions. The following properties are not in the BeanDefinition, but just for easy understanding. Beandefinitions actually just define their getters and setters:

  • BeanClassName: The class name of the bean
  • Scope: Scope of the bean
  • LazyInit: lazy loading or not
  • Primary: If there are more than one implementation class, this one is preferred
  • FactoryBeanName: Specifies the factory bean (if any) to use. This is the name of the bean used to invoke the specified factory method
  • FactoryMethod: specifies the factoryMethod (if any). This method is called with constructor arguments, or no arguments if not specified. This method will be called on the specified factory bean (if any), otherwise it will be called as a static method on the local bean class.
  • ConstructorArgumentValues: access to the constructor parameters, read-only, internal use LinkedHashMap storage according to the index parameters.
  • PropertyValues: Property value of the Bean instance. The returned instance can be modified during bean factory post-processing.
  • DependsOn: Sets the name of the bean on which the bean is initialized. The Bean factory will ensure that these beans are initialized first.
  • AutowiredCandidate: Sets whether this bean is suitable for automatic wiring to other beans. This only affects type based autowiring, not name based autowiring. And Boolean methods :isAutowireCandidate()
  • InitMethodName: The name of the initialized function
  • DestroyMethodName: Destruction method name
  • Description: Adds a more readable description to the bean
  • ParentName: Indicates the parent name of the bean

The scope of the Bean

The scope of the Bean can be specified as: Singleton, Prototype, Request, Session, Application.

The scope of describe
singleton Default scope, singleton
prototype Archetypal pattern, where multiple object instances can be created
request A Bean with a life cycle of an Http request. That is, each Http request generates its own Bean instance. Only valid in ApplicationContext
session Beans with a life cycle of the entire Http. Only valid in ApplicationContext
application Scope is limited to the life cycle of the ServletContext

Anything we define from XML or annotations is parsed into a BeanDefinition, and Bean instances are generated from that BeanDefinition, similar to person.java ->Person.class->Person.

Several ways to instantiate an object

  • spring-config.xml

      
<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.xsd">
	<! --1. Create with the class's no-argument constructor -->
	<bean id="personA" class="com.xjm.model.Person" scope="singleton" lazy-init="true" primary="true"></bean>
	<! --2. Create from static factory -->
	<bean id="personB" class="com.xjm.model.PersonStaticFactory" factory-method="getPerson" scope="singleton"></bean>
	<! --> create factory
	<bean id="personFactory" class="com.xjm.model.PersonFactory"></bean>
	<bean id="personC" factory-bean="personFactory" factory-method="getPerson" scope="singleton"></bean>
</beans>
Copy the code
  • Person
public class Person {

	private String name;

	private Integer age;

	public Person(String name) {
		this.name = name;
	}

	public Person(a) {}public String getName(a) {
		return name;
	}

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

	public Integer getAge(a) {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public String toString(a) {
		return "Person{" +
				"name='" + name + '\' ' +
				", age=" + age +
				'} '; }}Copy the code
  • PersonFactory
public class PersonFactory {

	public Person getPerson(a) {
		return new Person("I am Kobe who created by PeronFactory"); }}Copy the code
  • PersonStaticFactory
public class PersonStaticFactory {

	public static Person getPerson(a) {
		return new Person("I am James who created by PersonStaticFactory"); }}Copy the code
  • demo
@SuppressWarnings("all")
public class BeanDefinitionDemo {
	public static void main(String[] args) {
		// 1. Declare the class path configuration
		String xmlPath = "D: \ \ Spring \ \ Spring - framework - 5.1 x \ \ Spring - demo \ \ SRC \ \ the main \ \ resources \ \ Spring \ \ Spring - config. XML";
		// 2. Load the XML configuration class
		ApplicationContext applicationContext = new FileSystemXmlApplicationContext(xmlPath);
		System.out.println("****************Before Spring********************");
		// The default constructor
		Person person = new Person();
		System.out.println(person.toString());
		// Create Person using static methods
		Person kobe = PersonStaticFactory.getPerson();
		System.out.println(kobe.toString());
		// Create the Person using the factory
		PersonFactory personFactory = new PersonFactory();
		System.out.println(personFactory.getPerson().toString());
		System.out.println("****************Using Spring********************");
		// The default constructor creates the Bean
		Person personA = (Person) applicationContext.getBean("personA");
		// Create the Bean using the static factory method
		Person personB = (Person) applicationContext.getBean("personB");
		// Create the Bean using the factory method
		Person personC = (Person) applicationContext.getBean("personC");
		System.out.println(personA.toString()+"hashcode:"+personA.hashCode());
		System.out.println(personB.toString()+"hashcode:"+personB.hashCode());
		System.out.println(personC.toString()+"hashcode:"+personC.hashCode());
		System.out.println("************Singleton*********************");
		Person personAA = (Person) applicationContext.getBean("personA");
		Person personBB = (Person) applicationContext.getBean("personB");
		Person personCC = (Person) applicationContext.getBean("personC");
		System.out.println(personAA.toString()+"hashcode:"+personAA.hashCode());
		System.out.println(personBB.toString()+"hashcode:"+personBB.hashCode());
		System.out.println(personCC.toString()+"hashcode:"+personCC.hashCode()); }}Copy the code

As you can see, after the XML is configured with the corresponding initialization mode, Spring initializes the object instance according to the configured mode.

AbstractBeanDefinition

AbstractBeanDefinition is an abstract implementation of the BeanDefinition interface, meaning it defines code that can be reused by subclasses, providing some common parameters.

  • Class:beanClass, the Bean’s class object, or the fully qualified name of the class used to instantiate the Bean
  • Name: Name of the Bean
  • Scope:scope, the scope of the Bean
  • Constructor arguments: constructorArgumentValuesConstructor parameter, used during dependency injection
  • Properties:propertyValuesProperty, used for dependency injection
  • Autowiring mode:AUTOWIRE_NO,AUTOWIRE_BY_NAME,AUTOWIRE_BY_TYPE,AUTOWIRE_CONSTRUCTOR, automatic assembly way, byName, byType byConstructor
  • Lazy initialization mode:lazyInitLazy loading mode
  • Initialization method:initMethodNameInstantiation method, the hook function at instantiation time
  • Destruction method:destroyMethodNameDestruct method, the hook function at destruct time
  • Autowire candidate: autowireCandidateDeclare whether the bean can bea target for automatic assembly
  • primary(@Primary):primary, beans set to true will be the preferred implementation class, used in scenarios where a bean has multiple implementation classes
  • Factory bean name:factoryBeanName, factory class name
  • Factory method:factoryMethodName, specify the factory method (if any). This method is called with constructor arguments, or no arguments if not specified. This method will be called on the specified factory bean (if any), otherwise it will be called as a static method on the local bean class.

Here are some properties defined in AbstractBeanDefinition

BeanDefinition XML
scope
lazyInit
beanClass
autowireCandidate
primary
factoryMethodName To use getPerson alone, you need to be static
factoryBeanName


You create the personFactory, implement the interface to the FactoryBean, and then call the getPerson method based on getObject

BeanDefinition UML diagrams

OK, so AbstractBeanDefinition is a simple property declaration and constructor on a Beandefinition, The specific implementation is still implemented by GenericBeanDefinition, RootBeanDefinition, and ChildBeanDefinition, so what is the connection between the three? We’ll see in the next chapter

conclusion

  • Spring creates beans and BeanDefinitions to manage Java objects, then provides XML and annotations to read the configuration information, parse it into BeanDefinitions, and finally generate beans to register in the IOC container.
  • A bean can be instantiated using constructors, static factory methods, or factory instance methods (create the factory first and then call the method)
  • The methods of auto-assembly are byName, byType, and byConstructor
  • The life cycle of a Bean can be: Singleton, Prototype, Request, Session, Application, etc
  • The default IOC container is the hump rule for naming beans with initial letters. You can get your beans by specifying an alias