Summary of the container
The ApplicationContext, which represents the Spring IoC container implementation, is responsible for instantiating, configuring, and assembling beans. The container reads configuration metadata to get instructions about which objects to instantiate, configure, and assemble. Configuration metadata can be rendered using XML, Java annotations, or Java code. It allows you to handle interdependencies between your application’s objects and other objects.
Configuring metadata
Configuration using XML is simple and intuitive for getting started
Annotation-based configuration: @Compont(@serivcE @Controller @Repository) @Autowride Spring 2.5 supports annotation-based metadata configuration. The use of SSM framework development
Java-based configuration: @confiration @bean @import Since Spring 3.0, the functionality provided by the Spring JavaConfig project has been part of the Spring core framework. Therefore, you can use Java configuration instead of XML configuration to define external beans. Since spring4.0 support for springboot1.0, springboot has been developed entirely in javaConfig.
Instantiation of a container
Objects are created when the Spring container is created, not when they are needed (similar to the hungry Guy design pattern).
First configure the beans in the spring-IOC.xml configuration file
<? The XML version = "1.0" encoding = "utf-8"? > <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"> <bean class="com.jony.beans.User" id="user"></bean> </beans>Copy the code
Next, load spring-IOC.xml in your code
/ / load the spring container / / ApplicationContext at the top of the spring core interface / / ClassPathXmlApplicationContext according to project path / / XML configuration to instantiate the spring container FileSystemXmlApplicationContext according to the XML configuration of disk path to instantiate the spring container / / AnnotationConfigApplicationContext according to javaconfig To configure the instantiation of the spring container / / instantiate will load all the container bean ApplicationContext ioc = new ClassPathXmlApplicationContext (" spring - ioc. XML ");Copy the code
Write test code
In our test code, we can use the Bean objects that Spring IOC helped us inject in three ways.
package com.jont.ioc; import com.jony.beans.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; Public class IocTest {@test public void test01(){// Load the spring container //ApplicationContext spring's top core interface // ClassPathXmlApplicationContext according to project path of XML configuration to instantiate the spring container / / FileSystemXmlApplicationContext according to the XML configuration of disk path to instantiate the spring container / / AnnotationConfigApplicationContext configuration according to javaconfig instantiate the spring container / / instantiate will load all the container bean ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml"); User bean = ioc.getbean (user.class); User bean1= (User) ioc.getbean (" User "); User bean2= ioc.getbean (" User ", user.class); System.out.println(bean); }}Copy the code
Configuration of the Spring configuration file
Hold CTRL to go to view beans
Overview of the bean
As you can see in the figure below, there are three types of labels you can use for Beans
Bean: Import a class and let Spring inject it for us
You can also use name to define an alias, as follows:
<bean class="com.jony.beans.User" id="user" name="user2 user3,user4; user5"></bean>Copy the code
Import: If there is more than one XML file, you can use the import import to load it together
<? The XML version = "1.0" encoding = "utf-8"? > <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"> <bean class="com.jony.beans.User" id="user"></bean> <import resource="spring-ioc2.xml"></import> </beans>Copy the code
We can set an alias for the bean we have defined as follows
Using aliases in code can also use injected beans, and the original name can also be used
Dependency injection
Dependency injection based on setter methods
The XML configuration
<! Setset-based dependency injection 1. Property must declare the set method 2. Name is derived from the name of the set method. SetIdxx ‐> name="idxx" --> <bean class=" com.jony.beans.user "id ="userioc"> <property name="id" value="1"></property> <property name="userName" value="zhangsan"></property> <property name="realName" value="zhangsan"></property> </bean>Copy the code
Java code testing
Constructor-based dependency injection
The custom constructor will be called to instantiate the object and the default no-argument constructor will not be called
1. Inject according to attribute name
The XML configuration
Java code testing
2. Inject according to the subscript position
From the figure above, we can see that the contents of the bean can be injected without filling in the name attribute,Note that the order needs to be the same as the constructor order, otherwise it will match incorrectlyThat is as follows:
3, set index index to correct errors
The injection is done in the order of the constructors, so that the injection succeeds
4. Set the type of the property
Setting the type attribute can also set parameters, but if the parameters are of the same type, they will not match exactly. I’m not going to do the demo here
Conclusion: It is best to use the name attribute when injecting, so that you do not have to worry about injection errors even if the order is wrong.
Complex data dependency injection
Prepare the basics
Create a Person class with different types
package com.jony.beans; import java.util.Date; import java.util.List; import java.util.Map; public class Person { private Integer id; private String name; private String gender; private Date birthday; private List<String> hobbies; private Map<Integer,String> course; private Wife wife; public Person() { } public Person(Integer id, String name, String gender, Date birthday, List<String> hobbies, Map<Integer, String> course, Wife wife) { this.id = id; this.name = name; this.gender = gender; this.birthday = birthday; this.hobbies = hobbies; this.course = course; this.wife = wife; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + ''' + ", gender='" + gender + ''' + ", birthday=" + birthday + ", hobbies=" + hobbies + ", course=" + course + ", wife=" + wife + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public List<String> getHobbies() { return hobbies; } public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; } public Map<Integer, String> getCourse() { return course; } public void setCourse(Map<Integer, String> course) { this.course = course; } public Wife getWife() { return wife; } public void setWife(Wife wife) { this.wife = wife; }}Copy the code
Create a memorable class
package com.jony.beans; public class Wife { private Integer age; private String name; @Override public String toString() { return "Wife{" + "age=" + age + ", name='" + name + ''' + '}'; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Wife() { } public Wife(Integer age, String name) { this.age = age; this.name = name; }}Copy the code
1. Introduce external beans
The XML configuration
Set ref in the application class to the id of the referenced class
<bean class="com.jony.beans.Person" id="person"> <property name="id" value="1"></property> <! -- NULL --> <property name="name"> < NULL ></null> </property> <property name="gender" value=""></property> <! <property name="wife" ></property> </bean> <bean class=" com.jony.beans.wife "id="wife"> </property> <property name="age" value="24"></property> </bean>Copy the code
Java code and execution results
You can see that Person can be injected successfully through the external class referenced by ref
2. Introduce internal beans
The XML configuration
We set wife directly in the bean and then refer to the class address
<bean class="com.jony.beans.Person" id="person"> <property name="id" value="1"></property> <! -- NULL --> <property name="name"> < NULL ></null> </property> <property name="gender" value=""></property> <! <property name="wife"> <bean class=" com.jony.beans.wife "> <property name="name" </property> <property name="age" value="24"></property> </bean> </property> </bean>Copy the code
3, the list value
The XML configuration
To set a hobby for Person, the following is a String value, but you can also set other types
<bean class="com.jony.beans.Person" id="person"> <property name="id" value="1"></property> <! -- NULL --> <property name="name"> < NULL ></null> </property> <property name="gender" value=""></property> <! Property name="wife" ref="wife"></property> <! <bean> List <bean> List <bean> List <bean> List<Wife> <bean>--> <property name="hobbies"> < List > <value> sing </value> <value> dance </value> </ List > </property> </bean>Copy the code
Java test code and results
4, the map values
XML code
<! Map setting allows you to set key and value values directly. You can also set key-ref/value-ref if map value is object, then we can set value-ref to wife--> <property name="course"> <map> <entry key="1" value="Java"></entry> <entry key="2" value="Python"></entry> <entry key="3" value-ref="wife"></entry> </map> </property>Copy the code
The execution result
5. Use the p namespace
You can simplify injection based on setter properties by using the P namespace, which does not support collections
The XML configuration is as follows
At this time, I did not find that the p command is marked red, we just need to import the package in the P label by Alt+ Enter
You can see the XML header entry as follows
Then we set the value of lesson 3 to wife2 as follows:
Java Execution results
3. Use the c namespace
The XML configuration
Note that, unlike the P namespace, the C namespace must be a constructor
<! <bean class=" com.jony.beans.wife "id="wife3" c:age="23" C :name=" a beautiful woman "></bean>Copy the code
Advanced features
1. Depends on attributes
In spring-IOC. XML, the default loading order is from top to bottom. By using the Depends -on attribute, you can set the bean to be loaded first, that is, to control the loading order of beans
The XML configuration
Java Execution results
As you can see, because we set depends-on=”wife”, wife is loaded first and then person is loaded.
Lazy load lazy-init
You can set the bean to lazy-loaded by setting lazy-init, which is loaded only when it is used.
The XML configuration
<bean class="com.jony.beans.User" id="user" lazy-init="true"> <property name="id" value="1"></property> <property </property> </bean>Copy the code
Java Test results
In the figure below, we can see that the Spring-IOC configuration file was loaded when the test method was executed. Because User set lazy-init, it was not loaded until we used the User bean.
3. Automatic injection
When an object needs to reference another object, it is manually configured through the property tag in the previous configuration. In fact, spring also provides a very powerful function that is automatic assembly, which can be configured according to the rules specified by us. The configuration methods are as follows:
3-1. ByType is automatically injected based on type
Assemble according to the type, find the component in the container according to the type of the attribute. If there are multiple bean objects of the same type, an exception will be reported, and null will be assembled if it cannot be found
The XML configuration
You can see that we added autowrite=”byType” to the Person bean so that the properties in Person are automatically injected based on the type
<bean class="com.jony.beans.Person" id="person" depends-on="wife" autowire="byType"></bean> <bean class="com.jony.beans.Wife" id="wife"> <property name="age" value="24"></property> <property name="name" </property> </bean>Copy the code
The test results
We didn’t configure the Person wife in XML, but with automatic injection, Spring will automatically inject by type for us.Let’s modify the XML again as follows:
With two wives, the Person Autowrite will report an error because the same type occurs more than once and Spring doesn’t know which bean we want to assemble. If this happens, we can handle it using byName
3-2. ByName is automatically matched based on the name of the set method
For example, the set method for wife in Person is setWife and the name is wife
The XML configuration
The test results
You can see that spirng selects a bean with the name wife for automatic injectionWhat if we changed Person’s setWife to setWife2? Let’s test that out
XML is as follows
Setwife setWife2 instead
The execution result
She’s gone from a pretty girl to a pretty girl
Constructor installs the constructor for matching
The type of the parameter constructor is first assembled, and null is not directly assembled. If more than one is found by type, the match continues using the parameter name as id, and the match is assembled if it is found, and null if it is not found
The XML configuration
Modify the constructor of Person
The test results
We modify the Person constructor again, which is passed in to Wife2
Execute test method
conclusion
When the constructor is used for automatic injection, the XML will be matched by the name of the parameter passed in by the constructor. For example, if we pass wife, then wife2, the result will be different.
Constructor (byName); null (byType); constructor (multiple arguments); constructor (byType); Let’s say we add a parameter to the constructor of Person
Run the code again, and wife in Person will be null. This is mainly because the second parameter needs to be in the IOC container to be injected automatically, if we modify the constructor again as follows:
3We change the second parameter to User. The User bean is also injected into the XML file, so it can be injected through the constructor.
Therefore, the constructor does a full matching injection based on the parameters. If the parameters in the constructor do not exist in the IOC container, the automatic injection cannot be completed.
If a constructor parameter matches more than one bean byType in the container, the bean can be injected first by setting primary=”true”. As follows:
Set primart=true for the first wife bean
The scope of the Bean
1. Singleton scope
Spring uses singleton mode for bean injection by default to save system resources by not creating the same object multiple times in memory.
The test code is as follows
As you can see in the figure below, we created two User beans using getBean, but the no-argument constructor in User is executed only once, which means that our User Bean is singleton and created only once.
2, Prototype scope
The XML configuration
You can see that we added scope=”prototype” to the bean.
<bean class="com.jony.beans.User" id="user" lazy-init="true" scope="prototype"> <property name="id" Value ="1"></property> <property name="realName" ></property>Copy the code
Test Execution Result
You can see that by setting the stereotype scope, we create a new bean when we create a new object.
Other scopes
These last four scopes are described later because of the need to use Web services.If you are interested, you can go and have a look at the original:Docs. Spring. IO/spring – fram…
The characteristics of bean
The life cycle of the bean
1. What cycle of callback is implemented by implementing the interface
-
InitializingBean overrides the afterPropertiesSet method to initialize a method that will be called automatically
-
Implement interface: DisposableBean Automatically calls the destroy method when you override it
2. Implement lifecycle callbacks using specified methods:
Create the corresponding two methods in the corresponding bean
- Init ‐ method = “init” destroy ‐ method = “destroy”
The XML configuration
Java method
To distinguish interfaces from XML, each implementation of the interface is set to tag 1 and the implementation is configured to tag 2
3. When will beans be destroyed
IOC initializations need to be created in one of the following three ways. If the top-level core interface is used, there is no COLse method.
ClassPathXmlApplicationContext according to project path of XML configuration to instantiate the spring container FileSystemXmlApplicationContext according to the XML configuration of disk path to instantiate the spring container AnnotationConfigApplicationContext configuration according to javaconfig instantiate the spring containerCopy the code
Close () when the Spring container closes
The test results
From the above, we can see that both the create and destroy methods of the interface are executed first, so that if we need to monitor bean creation and destruction, we can do it in either way.
Spring creates third-party bean objects
In Spring, many objects are singletons. In daily development, we often need to use some external singletons, such as database connection pools. Let’s explain how to create third-party bean instances in Spring. For example, we introduce a database connection to, as follows
Database connection pool
1. Import the POM file of the database connection pool
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.21</version> </dependency> <! -- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> < artifactId > mysql connector - Java < / artifactId > < version > 8.0.28 < / version > < / dependency >Copy the code
2. Write a configuration file
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="username" value="root"></property> <property name="password" value="root"></property> <property name="url" value="jdbc:mysql://localhost:3306/jony"></property> <property name="driverClassName" value="com.mysql.jdbc.Driver"> </property> </bean>Copy the code
3, test,
@Test
public void test04(){
DruidDataSource dataSource=ioc.getBean("datasource",DruidDataSource.class);
System.out.println(dataSource);
System.out.println(dataSource.getConnectCount());
}
Copy the code
The execution result
Spring introduces external files
In a real project, we would write all the relevant resource configuration information into a resource file, so that when changes are made, we do not have to go to the Java code to make changes.
1. Add the configuration file to resource
For example, I add dbconfig.properties to the resource file for configuring database connection information
username=root
password=123456
url=jdbc:mysql://localhost:3306/demo
driverClassName=com.mysql.jdbc.Driver
Copy the code
Have Spring read the configuration file at injection time
The core is to import the configuration file we need to read using the following configuration
Then import the desired namespace, starting with XML
<context:property-placeholder location="classpath:dbconfig.properties"/>
Copy the code
3. The execution result is as follows
Use of Spring SpEL
SpEL:Spring Expression Language, the Spring Expression Language, supports runtime query operation objects using #{… } As a syntax rule, all characters in braces are considered SpEL.
Spring gives us the following expressions that we can use
1. XML configuration
<bean class="com.jony.beans.User" id="user2"> <! - support any operator Subtracting etc - > < property name = "id" value = "# {12 * 2}" > < / property > <! <property name="userName" value="#{address.type}"></property> <! <property name="realName" value="#{address}"></property> <! <property name="hobbies" value="#{T(java.util.uuid).randomuuid ().tostring ().substring(0,4)}"></property> <! <property name="gender" value="#{address.getCity()}"></property> </bean>Copy the code
Note: If you use a static method, you need to use T to represent it, as in the hobbies reference UUID above.