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 Bean
BeanDefinition
, 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@Autowired
Injecting 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,
ApplicationContext
The 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 XML
scope="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.
- 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
- 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:
constructorArgumentValues
Constructor parameter, used during dependency injection - Properties:
propertyValues
Property, 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:
lazyInit
Lazy loading mode - Initialization method:
initMethodName
Instantiation method, the hook function at instantiation time - Destruction method:
destroyMethodName
Destruct method, the hook function at destruct time - Autowire candidate:
autowireCandidate
Declare 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