Spring中有两种Bean,一种是普通的Bean,另外一种就是FactoryBean。FactoryBean与普通的Bean不同,其返回的对象不是指定类的一个实例,而是该FactoryBean的getObject方法所返回的对象。创建出来的对象的类型由getObjectType方法决定,是否是单例由isSingleton方法决定。上面提到的这个三个方法就组成了FactoryBean接口。
package org.springframework.beans.factory;
import org.springframework.lang.Nullable;
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
FactoryBean 通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>LearnFactoryBean</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
</dependencies>
</project>
.
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── wangjun
│ │ │ └── test
│ │ │ ├── Main.java
│ │ │ ├── TestFactoryBean.java
│ │ │ ├── TestInterface.java
│ │ │ ├── TestInterfaceImplA.java
│ │ │ └── TestInterfaceImplB.java
│ │ └── resources
│ │ └── spring.xml
public interface TestInterface {
void name();
}
public class TestInterfaceImplA implements TestInterface {
public void name() {
System.out.println("impl:a");
}
}
public class TestInterfaceImplB implements TestInterface {
public void name() {
System.out.println("impl:b");
}
}
public class TestFactoryBean implements FactoryBean<TestInterface> {
private Class<?> testInterface;
/**
* 随机返回TestInterface接口的实现类A或实现类B
* @return
* @throws Exception
*/
public TestInterface getObject() throws Exception {
return new Random().nextInt(2) == 0? new TestInterfaceImplA(): new TestInterfaceImplB();
}
/**
* 返回bean的类型
* @return
*/
public Class<?> getObjectType() {
return testInterface;
}
public void setTestInterface(Class<?> testInterface) {
this.testInterface = testInterface;
}
public void test() {
System.out.println("test1111");
}
}
<?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 name="testFactoryBean" class="com.wangjun.test.TestFactoryBean">
<property name="testInterface" value="com.wangjun.test.TestInterface"/>
</bean>
</beans>
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring.xml");
TestInterface testInterface = context.getBean(TestInterface.class);
// 也可以这样获取bean
// TestInterface testInterface = (TestInterface) context.getBean("testFactoryBean");
testInterface.name();
// 如果需要获取实现了FactoryBean的实例FirstFactoryBean,而不是getObject返回的实例,则需要在beanName前加&
// 参考:https://stackoverflow.com/questions/49199901/what-does-the-mean-in-in-a-bean-name
FirstFactoryBean f = (FirstFactoryBean) context.getBean("&shareInterface");
f.test();
}
}