Spring 容器中有两种bean :
FactoryBean接口对于Spring框架来说占有重要的地位,Spring 自身就提供了很多FactoryBean的实现。它们隐藏了实例化一些复杂bean的细节,给上层应用带来了便利。
从Spring 3.0 开始, FactoryBean开始支持泛型,即接口声明改为FactoryBean 的形式。
官方地址:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-extension-factorybean
You can implement the org.springframework.beans.factory.FactoryBean interface for objects that are themselves factories.
The FactoryBean interface is a point of pluggability into the Spring IoC container’s instantiation logic. If you have complex initialization code that is better expressed in Java as opposed to a (potentially) verbose amount of XML, you can create your own FactoryBean, write the complex initialization inside that class, and then plug your custom FactoryBean into the container.
The FactoryBean interface provides three methods:
The FactoryBean concept and interface are used in a number of places within the Spring Framework. More than 50 implementations of the FactoryBean interface ship with Spring itself.
When you need to ask a container for an actual FactoryBean instance itself instead of the bean it produces, prefix the bean’s id with the ampersand symbol (&) when calling the getBean() method of the ApplicationContext. So, for a given FactoryBean with an id of myBean, invoking getBean(“myBean”) on the container returns the product of the FactoryBean, whereas invoking getBean(“&myBean”) returns the FactoryBean instance itself.
简述:
package com.lot.learn.spring.factorybean;
import lombok.Data;
@Data
public class MySqlSession {
private Long id;
public MySqlSession(Long id) {
this.id = id;
}
}
package com.lot.learn.spring.factorybean;
import lombok.Data;
import org.springframework.beans.factory.FactoryBean;
@Data
public class MySqlSessionFactory implements FactoryBean {
private Long id;
private Long sessionId;
@Override
public MySqlSession getObject() {
return new MySqlSession(sessionId);
}
@Override
public Class> getObjectType() {
return MySqlSession.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
spring-factorybean.xml
org.springframework
spring-context
5.2.9.RELEASE
org.springframework
spring-jdbc
5.2.9.RELEASE
org.springframework
spring-test
5.2.9.RELEASE
package factorybean;
import com.lot.learn.spring.factorybean.MySqlSession;
import com.lot.learn.spring.factorybean.MySqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring-factorybean.xml" })
public class TestFactoryBean {
@Autowired
private MySqlSessionFactory userFactory1;
@Autowired
private MySqlSession mySqlSession1;
@Autowired
private ApplicationContext context;
@Test
public void test() {
System.out.println("factory.getId() = " + userFactory1.getId());
// 我们并没有配置 MySqlSession 仍可以注入
System.out.println("mySqlSession.getId() = " + mySqlSession1.getId());
// by Type
MySqlSession mySqlSession2 = context.getBean(MySqlSession.class);
MySqlSessionFactory userFactory2 = context.getBean(MySqlSessionFactory.class);
// by name
MySqlSession mySqlSession3 = (MySqlSession) context.getBean("mySqlSession");
MySqlSessionFactory userFactory3 = (MySqlSessionFactory) context.getBean("&mySqlSession");
// 以下都是 true
System.out.println("mySqlSession1 == mySqlSession2 :" + (mySqlSession1 == mySqlSession1));
System.out.println("userFactory1 == userFactory2 :" + (userFactory1 == userFactory1));
System.out.println("mySqlSession2 == mySqlSession3 :" + (mySqlSession2 == mySqlSession3));
System.out.println("userFactory2 == userFactory3 :" + (userFactory2 == userFactory3));
}
}
根据打印结果看, 已经验证上述问题
factory.getId() = 9999
mySqlSession.getId() = 1
mySqlSession1 == mySqlSession2 :true
userFactory1 == userFactory2 :true
mySqlSession2 == mySqlSession3 :true
userFactory2 == userFactory3 :true
现阶段使用 FactoryBean 创建对象的使用习惯越来越少, 有很多其他更方便创建方式: