1.FactoryBean定义
Interface to be implemented by objects used within a {@link BeanFactory} which
* are themselves factories for individual objects. If a bean implements this
* interface, it is used as a factory for an object to expose, not directly as a
* bean instance that will be exposed itself
实现该接口的Bean被当做BeanFactory用来产生单个对象,暴露的是产生的对象并不是当前Bean
2.FactoryBean示例
2.1 定义Bean
@Component
public class UserFactoryBean implements FactoryBean<User> {
}
2.2 指定返回对象
@Override
public User getObject() throws Exception {
return new User();
}
2.3 指定返回类型
@Override
public Class<?> getObjectType() {
return User.class;
}
2.4 完整示例
@Component
public class UserFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
return new User();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}
3.Bean与暴露对象
通常情况下要获取容器中的Bean对象,只需要通过beanFactory.getBean("bean名称")方法即可得到结果,来看看下面的示例
beanFactory.getBean("userFactoryBean");
控制台输出结果:
User(id=null, name=null, age=null)
通过控制台可以看出并非是我们预想的结果,如果想要获取UserFactoryBean,又该怎么做呢?只需要在Bean名称前面添加"&"
beanFactory.getBean("&userFactoryBean");
控制台输出结果:
com.boot.example.factory.UserFactoryBean@5273143e
3.1 实现原理
3.1.1 名称转换
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
// 如果Bean的名称不是以"&"开头,直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
// 如果Bean的名称以"&"开头,则进行截取。例如传入Bean的名称为”&userFactoryBean“,处理之后的结果为”userFactoryBean“
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
3.1.2 获取实例
// 根据Bean名称从容器中获取实例
Object sharedInstance = getSingleton(beanName);
3.1.3 获取目标对象
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 1.如果Bean名称以”&“开头
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
// 2.直接返回实例对象
return beanInstance;
}
// 3.如果实例对象不是FactoryBean类型直接返回
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
// 4.从缓存中获取目标对象
object = getCachedObjectForFactoryBean(beanName);
}
// 5.缓存在不存在目标对象
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 6.从FactoryBean中获取目标对象
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
3.1.4调用 FactoryBean的getObject()
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
// 调用FactoryBean的getObject()方法,得到目标对象
object = factory.getObject();
}
}
return object;
}
3.1.5 缓存目标对象
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 调用FactoryBean的getObject()方法,得到目标对象
object = doGetObjectFromFactoryBean(factory, beanName);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
} else {
if (containsSingleton(beanName)) {
// 将目标对象进行缓存,避免重复创建
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
}
3.1.6 总结
- beanFactory.getBean("&userFactoryBean")从容器中获取
Bean对象 - beanFactory.getBean("userFactoryBean")先从容器中获取
Bean对象,调用Bean对象的getObject()方法获取目标对象