Spring factory method creates (instantiates) bean instance code
- 2020-12-19 20:59:21
- OfStack
Specific goals
A brief description of the problem this article addresses is how to move the Bean creation process from Spring to Bean instances in Spring.
clear
How to create an Bean instance:
1) Through the constructor (with or without parameters)
Method:
<bean id="" class=""/>
2) Through the static factory method
Method:
<bean id="" class="工厂类" factory-method="静态工厂方法"/>
Note: The factory class instance was not created
3) Through the instance factory method (non-static method)
Method:
<bean id="factory" class="工厂类"/>
<bean id="" factory-bean="factory" factory-method="实例工厂方法"/>
Note: Instances of factory classes are created
Methods the practical
Example 1:
Requirements:
1 Instead of instantiating bean when bean.xml is loaded, you want to separate the loading of ES48en.xml from the instantiated object.
bean for singletons
In all of the above cases, bean can be created using the factory method ES55en-ES56en.
In this way, when bean.xml is reloaded, bean is not instantiated directly, but the actual instantiation begins when the method referred to by factory-ES64en is called.
Implementation: bean singleton is created using ES68en-ES69en of spring
First, create a singleton object with a static inner class
package com.spring.test.factorymethod;
public class Stage {
public void perform(){
System.out.println(" Show began ...");
}
private Stage(){
}
private static class StageSingletonHolder{
static Stage instance = new Stage();
}
public static Stage getInstance(){
return StageSingletonHolder.instance;
}
}
Specify the method getInstance to load in the spring configuration file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="theStage" class="com.spring.test.factorymethod.Stage"
factory-method="getInstance"></bean>
</beans>
Call bean to get the instance from the application context
package com.spring.test.factorymethod;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
Stage stage = ((Stage)ctx.getBean("theStage"));//.getInstance();
stage.perform();
}
}
The execution result
1 month 24, 2015 6:38:18 In the afternoon org.springframework.context.support.AbstractApplicationContext prepareRefresh
information : Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@512dbd1a: startup date [Sat Jan 24 18:38:18 CST 2015]; root of context hierarchy
1 month 24, 2015 6:38:19 In the afternoon org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
information : Loading XML bean definitions from class path resource [bean.xml]
1 month 24, 2015 6:38:19 In the afternoon org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
information : Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2d1879ea: defining beans [duke,sonnet29,poeticDuke,theStage]; root of factory hierarchy
Show began ...
The factory method to create bean is described
1. Create Bean using the static factory method
When you create an instance of Bean using a static factory method, the class attribute must also be specified, but in this case the class attribute does not specify an implementation class for an instance of Bean, but a static factory class. Because Spring needs to know which factory is used to create the Bean instance. In addition, factory-method will be used to specify the static factory method name. Spring will call the static factory method (which may contain a set of parameters) to return 1 instance of Bean. Once the specified Bean instance is obtained, the processing steps following Spring are exactly the same as creating an Bean instance using the normal method. It is important to note that when using static factory methods to create Bean, the ES108en-ES109en must be static. This explanation sounds a little confusing, without further ado, code:
Define an interface, and the static method will produce an instance of the interface:
public interface Animal {
public void sayHello();
}
Here are the two implementation classes for the interface:
public class Cat implements Animal {
private String msg;
// Dependency injection is required setter methods
public void setMsg(String msg){
this.msg = msg;
}
@Override
public void sayHello(){
System.out.println(msg + " Meow, ~ meow ~");
}
}
public class Dog implements Animal {
private String msg;
// Dependency injection is required setter methods
public void setMsg(String msg){
this.msg = msg;
}
@Override
public void sayHello(){
System.out.println(msg + " , ~ swan ~");
}
}
The AnimalFactory factory below contains a static method of getAnimal that will determine which object to create based on the parameters passed in. This is a typical static factory design pattern.
public clas AnimalFactory {
public static Animal getAnimal(String type){
if ("cat".equalsIgnoreCase(type)){
return new Cat();
} else {
return new Dog();
}
}
}
If you want to specify Spring to use AnimalFactory to generate Animal objects, you can do the following in the Spring configuration file:
<!-- configuration AnimalFactory the getAnimal Method to make it come into being Cat -->
<bean id="cat" class="com.abc.AnimalFactory" factory-method="getAnimal">
<!-- Configure the parameters of the static factory method, getAnimal Method will produce Cat Object of type -->
<constructor-arg value="cat" />
<!-- through setter Injected common properties -->
<property name="msg" value=" The cat cat " />
</bean>
<!-- configuration AnimalFactory the getAnimal Method to make it come into being Dog -->
<bean id="dog" class="com.abc.AnimalFactory" factory-method="getAnimal">
<!-- Configure the parameters of the static factory method, getAnimal Method will produce Dog Object of type -->
<constructor-arg value="dog" />
<!-- through setter Injected common properties -->
<property name="msg" value=" dog " />
</bean>
As you can see from the above configuration: cat and dog are identical to class and ES134en-ES135en for both Bean configurations, because both instances are generated using the same static factory class and the same static factory method. It is just that the parameters specified for the static factory method are different < constructor-arg / > Element to specify parameters for static factory methods.
The main program gets cat and dog instances without changing the method. Again, it only needs to call getBean() of the Spring container:
public class Test {
public static void main(String args[]){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
Animal a1 = context.getBean("cat", Animal.class);
a1.sayHello();
Animal a2 = context.getBean("dog", Animal.class);
a2.sayHello();
}
}
Output results:
<code class="hljs"> The cat cat, meow ~ meow ~
Dogs, flourishing ~ swan ~</code>
When you create an instance using a static factory method, you must provide the factory class and the static factory method that generated the instance. You need to make the following changes to the Spring configuration file when you create an instance using the static factory method;
The class attribute is no longer an implementation class for an Bean instance, but a static factory class that generates an Bean instance
Use ES160en-method to specify a static factory method for producing Bean instances
If static factory methods require parameters, use < constructor-arg / > Element for which it is configured
When we specify Spring use the static factory methods to create Bean instance, Spring will parse configuration files, and according to the configuration file specified information, through reflection to invoke static factory class static factory methods, and the static factory methods return values as Bean instance, in the process, Spring no longer responsible for creating Bean instance, Bean instance is provided by the user provides static factory methods.
2. Create Bean using the instance factory method
Instance factory methods differ from static factory methods in only one respect: to invoke a static factory method, you only need to use the factory class; to invoke an instance factory method, you must use the factory instance. So there is only one difference in Spring configuration: the configuration static factory method specifies the static factory class, and the configuration instance factory method specifies the factory instance. In the same example above, AnimalFactory is modified to:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="theStage" class="com.spring.test.factorymethod.Stage"
factory-method="getInstance"></bean>
</beans>
0
The Spring file is modified to:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="theStage" class="com.spring.test.factorymethod.Stage"
factory-method="getInstance"></bean>
</beans>
1
The test class is not modified, and the output is the same as above.
It's used in many cases
<
bean id bean1 class = "="..." /
>
Define an bean, which will call the default no-argument constructor to create an instance of Bean. In addition, Bean instances can be created in factory mode to achieve the separation of Bean creation and use, leaving Bean creation to the factory.
Three ways to configure factory Bean.
Abstract interface:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="theStage" class="com.spring.test.factorymethod.Stage"
factory-method="getInstance"></bean>
</beans>
2
1. Static factory method to obtain Bean instance
The factory class:
public class MusicBoxFactory {
public static IMusicBox createMusicBox(){
return new IMusicBox(){
public void play(){
System.out.println("Play piano...");
}
};
}
}
Configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="theStage" class="com.spring.test.factorymethod.Stage"
factory-method="getInstance"></bean>
</beans>
4
The test class:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="theStage" class="com.spring.test.factorymethod.Stage"
factory-method="getInstance"></bean>
</beans>
5
2. Obtain the Bean instance by the method of the factory instance
The factory class:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="theStage" class="com.spring.test.factorymethod.Stage"
factory-method="getInstance"></bean>
</beans>
6
Configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="theStage" class="com.spring.test.factorymethod.Stage"
factory-method="getInstance"></bean>
</beans>
7
The "ES237en-ES238en" attribute specifies the factory Bean, and the "ES240en-ES241en" attribute specifies the factory method to obtain the Bean instance.
The test class:
public static void main(String[] args) {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("bean-config.xml");
IMusicBox musicbox = (IMusicBox)ctx.getBean("musicBox");
musicbox.play();
}
3, the factory class implements org. springframework. beans. factory. FacotryBean interface
The factory class:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="theStage" class="com.spring.test.factorymethod.Stage"
factory-method="getInstance"></bean>
</beans>
9
Configuration file:
<bean id="musicBox" class="test.spring.MusicBoxFactory2"/>
The test class:
public static void main(String[] args) {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("bean-config.xml");
// Do not add & "Products" returned to the factory
IMusicBox musicbox = (IMusicBox)ctx.getBean("musicBox");
musicbox.play();
// add & Returns the factory class instance
Object obj = ctx.getBean("&musicBox");
System.out.println(obj.getClass().getName());
}
A class that implements the FactoryBean interface will not be treated as a normal Bean, and Spring will automatically detect and call the getObject method to get an instance of Bean
conclusion
Spring factory method instantiation bean instance introduction is here, any shortcomings, you can leave a comment. Thank you for your support!