This is the second day of my participation in the August Text Challenge.More challenges in August
V. Spring Factory
5.1. Simple and Complex Objects
5.1.1. Simple Objects
Simple objects are objects that can be created directly by calling the constructor (new).
5.1.2 Complex Objects
Complex objects are objects that cannot be created directly by calling the constructor (new). For example, JDBC Connection object, Mybatis SqlSessionFactory object.
5.2. Three ways Spring creates complex objects
5.2.1, FactoryBean
5.2.1.1. FactoryBean Interface
If the class attribute configured in the ApplicationContext.xml configuration file is the implementation class of the FactoryBean interface, then the id attribute is the complex object created by that class (the underlying getObject() method is called).
public class MyFactoryBean implements FactoryBean<Connection> {
// Write code that creates complex objects and returns them as the method's return value
@Override
public Connection getObject(a) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql:///javaweb? characterEncoding=utf-8&useSSL=false"."root"."123456");
return connection;
}
// Returns the Class object of the created complex object
@Override
publicClass<? > getObjectType() {return Connection.class;
}
// Whether the configuration is in singleton mode
@Override
public boolean isSingleton(a) {
return false;
}
Copy the code
<bean id="factoryBean" class="com.test.MyFactoryBean">
Copy the code
/** * is used to test factoryBean */
@Test
public void testFactoryBean(a){
ClassPathXmlApplicationContext ctr = new ClassPathXmlApplicationContext("/applicationContext.xml");
Connection conn = (Connection) ctr.getBean("factoryBean");
System.out.println(conn);
}
Copy the code
5.2.1.2 FactoryBean interface details
- If I don’t want to get the complex object I created (Connection), and I want to get the plain simple object (FactoryBean), we simply add one in front of the getBean (ID)
&
Can.
import java.sql.Connection;
import java.sql.DriverManager;
import org.springframework.beans.factory.FactoryBean;
/ * * *@Description
* @Author XiaoLin
* @Date2021/2/24 coast * /
public class MyFactoryBean implements FactoryBean<Connection> {
@Override
public Connection getObject(a) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager
.getConnection("jdbc:mysql:///javaweb? characterEncoding=utf-8&useSSL=false"."root"."1101121833");
return connection;
}
@Override
publicClass<? > getObjectType() {return Connection.class;
}
@Override
public boolean isSingleton(a) {
return true; }}Copy the code
<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 id="factoryBean" class="MyFactoryBean">
</bean>
</beans>
Copy the code
import java.sql.Connection;
import org.junit.Test;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/ * * *@Description
* @Author XiaoLin
* @Date2021/2/24 timnathserah * /
public class MyFactoryBeanTest {
/** * used to test the creation of complex type objects */
@Test
public void testMyFactoryBeanTest(a){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");
MyFactoryBean connection = (MyFactoryBean)applicationContext.getBean("&factoryBean");// Get the plain simple object FactoryBean, not the complex Connection objectSystem.out.println(connection); }}Copy the code
- The isSingleton() method creates only one object if it returns true, and multiple objects if it returns false. It is generally determined whether the object returns true(SqlSessionFactory) or false(Connection).
5.2.1.3 Implementation schematic diagram of BeanFactory
5.2.1.4 FactoryBean Summary
Factorybeans are a Spring method for creating complex objects. They are provided natively by Spring and will be used extensively in framework integration.
5.2.2 Example Factory
5.2.2.1 Disadvantages of FactoryBean
If you use FactoryBean, Spring invents it and implements the FactoryBean interface. Once you leave Spring, the entire class becomes unusable.
5.2.2.2 Use of example factories
// Example factory
public class ConnectionFactory {
public Connection getConnection(a){
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///javaweb? characterEncoding=utf-8&useSSL=false"."root"."1101121833");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
returnconn; }}Copy the code
<bean id="connFactory" class="com.factory.ConnectionFactory"/>
<bean id="conn" factory-bean="connFactory" factory-method="getConnection"/>
Copy the code
5.2.3 Static Factory
We learned about instance factories earlier. Since the getConnection() method of an instance factory is an instance method that needs to be called by an object, you need to create the object and then call the method from the object.
Because the getConnection() method is static, it does not need to be called by an object, but directly by a class. This is the biggest difference between an instance factory and a static factory.
public class ConnectionStaticBeanFactory {
public static Connection getConnection(a){
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///javaweb? characterEncoding=utf-8&useSSL=false"."root"."1101121833");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
returnconn; }}Copy the code
<bean id="staticBeanFactory" class="com.factory.ConnectionStaticBeanFactory" factory-method="getConnection"/>
Copy the code
5.3. Details of creating objects
5.3.1. Control the creation times of simple objects
To control the number of times a simple object is created, we simply need to configure the scope property value of the bean label. He usually uses two values:
- Singleton: Default to singleton mode, only one simple object is created.
- Prototype: Creates a new object each time.
<bean id="person" scope="singleton(prototype)" class="com.doamin.Person"/>
Copy the code
5.3.2 Control the creation times of complex objects
The return value of the isSingleton() method of the FactoryBean interface is used for control (if there is no isSingleton() method, then the scope property is used again) :
- Returns true: it will only be created once.
- Return false: a new object is created each time.
5.3.3 Reasons for the creation times of control objects
Objects that can be shared (SqlSessionFactory, daOs, services) can be created only once. Objects that cannot be shared (Connection, SqlSession, Controller) can be created multiple times. The biggest benefit of controlling the number of object creation times is that it saves unnecessary memory waste.
5.4 Object life cycle
The life cycle refers to the complete process of creating, living, and dying an object. Spring is responsible for creating, surviving, and destroying objects. Understanding the life cycle helps us use the objects Spring creates for us.
The objects Spring helps us create have three phases:
- Create a stage
- Initialization phase
- Destruction of phase
5.4.1 Creation Phase
- When scope = “singleton”, the object is created at the same time the Spring factory is created. If we don’t want to create it at the same time as the Spring factory and want to create it when we get the object, we simply add a lazy-init = true to the bean tag of the configuration file.
- When scope = “prototype”, the Spring factory creates the object at the same time it retrieves it.
5.4.2 Initialization Phase
After the object is created, the Spring factory calls the object’s initialization method to complete the corresponding initialization operation.
The initialization method is provided by the programmer according to the requirements, which is called by the Spring factory and finally completes the initialization operation. He can call in two ways:
- Implement the InitializingBean interface (with Spring intrusion issues).
- Provide a normal method and modify the configuration file.
5.4.2.1 InitializingBean interface
// This is the initialization method, do some initialization and Spring will call it
@Override
public void afterPropertiesSet(a) throws Exception {
// Initialize the operation
}
Copy the code
5.4.2.2 Provide common methods
Because of the problem of implementing the InitializingBean interface, Spring provides another method for us to initialize the operation. That is to provide a normal method, and then go to the configuration file to add init-method=” method name “familiar configuration.
public void init(a){
System.out.println("I'm the initializer.");
}
Copy the code
<bean id="product" class="com.domain.Product" init-method="init"/>
Copy the code
5.4.2.3, pay attention to
If an object implements both the InitializingBean interface and provides a normal initialization method, then both InitializingBean interface methods are executed first, followed by the normal initialization method.
The properties are injected before the initialization operation, before the injection and after the initialization.
Initialization operations include database, I/O, and network operations.
5.4.3 Destruction stage
Before the factory is shut down, Spring calls the object’s destruction method to complete the destruction operation before destroying the object.
The destruction method is defined by the programmer according to the requirements, and the Spring factory calls the destruction method to complete the destruction operation. He also has two methods:
- Implement the DisposableBean interface.
- Define common destruction methods to be configured in the configuration file.
5.4.3.1 Implement DisposableBean interface
public class Product implements InitializingBean.DisposableBean {
@Override
public void destroy(a) throws Exception {
System.out.println("Destroy operation, resource release"); }}Copy the code
5.4.3.2. Define common methods
public class Product implements InitializingBean.DisposableBean {
public void MyDestory(a){
System.out.println("Self-defined destruction method."); }}Copy the code
<bean id="product" class="com.domain.Product" destroy-method="MyDestory"/>
Copy the code
5.4.3.3, pay attention to
- The destruction method operation applies only to scope=”singleton”.
- A destroy operation is a resource release operation.
5.5. Spring integrates configuration files
Generally speaking, we will not write some configuration information like database directly in the code. We will extract them into a configuration file and use Spring to inject. All we need to do is add a tag.
<! Tell Spring where your db.properties is -->
<context:property-placeholder location="classpath:/db.properties"/>
<! $(db.properties key) -->
<bean id="conn" class="com.factory.BeanFactory">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
Copy the code
Custom type converters
6.1 type Converter
The values we assign in our Spring configuration files are strings, but our entity class is Interger. We can’t assign strings directly to Integer, syntactically.
Spring uses the type converter to convert the string data in the configuration file to the data of the corresponding type of the member variable in the object, thus completing the injection.
6.2. Custom Type Converters
6.2.1 Problem introduction
@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {
private String name;
private Date birthday;
}
Copy the code
<bean id="people" class="com.domain.People">
<property name="name" value="XiaoLin"/>
<property name="birthday" value="2021-2-6"/>
</bean>
Copy the code
A String value cannot be converted to a Date value, indicating that Spring does not have an internal converter.
Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.util.Date' for property 'birthday': no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:262) at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:585) . 39 moreCopy the code
Spring does not provide a specific type converter internally, and programmers need to use it in their applications, so programmers need to define their own type converters.
6.2.2 Code implementation
The custom type converter is implemented in two steps:
- implementation
Converter< Type before Conversion, Type after Conversion >
Interface, and override the methods inside. - The converter is registered in the configuration file
public class MyConverter implements Converter<String.Date> {// He has two generics, one for the pre-cast type and one for the post-cast type
Return: Take the converted value as the return value, and Spring will automatically assign a value to the property */
@Override
public Date convert(String source) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date parse = null;
try {
parse = sdf.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
returnparse; }}Copy the code
<! - type converter registration, told Spring we create MyConverter class is a class type converter, Spring provides a class ConversionServiceFactoryBean to complete type converter registration -- -- >
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters" >
<set>
<! Register type converter -->
<ref bean="myConvert"/>
</set>
</property>
</bean>
Copy the code
6.2.3 Pay attention to details
- create
ConversionServiceFactoryBean
Of the labelid
Must beconversionService
Otherwise, it will not take effect. - Spring already has a built-in date-type converter, but it only supports date-type converters
/
String format as delimiter: 2021/2/6, no other format is supported, if your string format is already this, there is no need to write a custom type converter.
Seven, BeanPostProcessor
7.1 overview,
BeanPostProcessor is called a post-processing Bean. Its role is to reprocess objects created by the Spring factory. It is the underlying implementation of AOP, and it is essentially an interface.
7.2 BeanPostProcessor analysis
It is an interface that implements its two methods:
Object postProcessBeforeInitialization(Object bean,String beanName)
After Spring has created the object, and before the initialization method,- Get the object created by Spring with parameters, and execute
postProcessBeforeInitialization
Method, and finally returns the processed object to Spring with a return value. Object postProcessAfterInitialization(Object bean,Stirng beanName)
: Runs after Spring completes the initialization of the objectpostProcessAfterInitialization
Method to retrieve the object created by Spring with parameters, and finally return it to Spring with a return value.
In daily development, we rarely deal with Spring initialization operations, so there is no need to distinguish between before and after, so generally only one method needs to be implemented, and BeanPostProcessor processes all objects in the Spring factory.
7.3. Code implementation
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private Integer id;
private String name;
}
Copy the code
public class MyBeanPoster implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// If it is not Student, it will return a cast error because Spring will process all the objects in the factory
if (bean instanceof Student){
Student student = (Student) bean;
student.setName("lisi");
}
returnbean; }}Copy the code
<bean id="student" class="com.beanpost.Student">
<property name="id" value="10"/>
<property name="name" value="zs"/>
</bean>
<! Register the backend Bean-->
<bean id="myBeanProcessor" class="com.beanpost.MyBeanPoster"/>
Copy the code