一般情况下,spring通过反射机制利用bean的class属性指定实现类来实例化bean。在某些情况下,实例化bean过程比较复杂,如果按照传统方式,灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。spring为此提供了一个org.springframework.beans.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑
下面展示 FactoryBean,注意看代码中的注释,注意看代码中的注释,注意看代码中的注释
。
package org.springframework.beans.factory;
import org.springframework.lang.Nullable;
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
//返回由FactoryBean创建的bean实例,如果isSingleton返回true,则该实例会放到Spring容器中单实例缓存池中。
@Nullable
T getObject() throws Exception;
//返回FactoryBean创建的bean类型
@Nullable
Class<?> getObjectType();
//返回由FactoryBean创建的bean实例的作用域是singleton还是prototype
default boolean isSingleton() {
return true;
}
}
当我们的类实现了FactoryBean时,通过applicationContext.getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法返回的对象,相当于FactoryBean#getObject()代理了getBean()方法。
例如:
下面展示 具体实现
。
// 定义一个MyFactoryBean类实现FactoryBean接口,重写其方法
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;
@Component
public class MyFactoryBean implements FactoryBean {
//返回自定义的功能类PersionServiceImpl
@Override
public Object getObject() throws Exception {
return new PersionServiceImpl();
}
//返回自定义的接口PersionService
@Override
public Class<?> getObjectType() {
return PersionService.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
public interface PersionService {
void printName();
}
public class PersionServiceImpl implements PersionService{
@Override
public void printName() {
System.out.println("===中路杀神====");
}
}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class FactoryBeanTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void ftest(){
PersionService persionService = applicationContext.getBean(PersionService.class);
persionService.printName();
}
}
运行结果如下
===中路杀神====
下面源码分析一波
AbstractApplicationContext#getBean()
public <T> T getBean(Class<T> requiredType) throws BeansException {
this.assertBeanFactoryActive();
return this.getBeanFactory().getBean(requiredType);
}
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
this.assertBeanFactoryActive();
//getBeanFactory()返回的是DefaultListableBeanFactory
return this.getBeanFactory().getBean(requiredType, args);
}
DefaultListableBeanFactory#getBean()
public <T> T getBean(Class<T> requiredType) throws BeansException {
return this.getBean(requiredType, (Object[])null);
}
public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
//这里我们重点看resolveBean()方法
Object resolved = this.resolveBean(ResolvableType.forRawClass(requiredType), args, false);
if (resolved == null) {
throw new NoSuchBeanDefinitionException(requiredType);
} else {
return resolved;
}
}
this.resolveBean()
@Nullable
private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
//NamedBeanHolder对应我们的例子 beanName是MyFactoryBean,beanInstance是PersionService
//下面看看resolveNamedBean是怎么做到的映射
NamedBeanHolder<T> namedBean = this.resolveNamedBean(requiredType, args, nonUniqueAsNull);
if (namedBean != null) {
return namedBean.getBeanInstance();
} else {
BeanFactory parent = this.getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory) {
return ((DefaultListableBeanFactory)parent).resolveBean(requiredType, args, nonUniqueAsNull);
} else if (parent != null) {
ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
if (args != null) {
return parentProvider.getObject(args);
} else {
return nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable();
}
} else {
return null;
}
}
}
resolveNamedBean()
@Nullable
private <T> NamedBeanHolder<T> resolveNamedBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
//这个方法是根据传入的Class类型来获取BeanName,因为我们有一个接口有多个实现类的情况(多态),
//所以这里返回的是一个String数组。
//这里需要注意的是,我们调用getBean方法传入的type为PersionService.class类型,但是我们在Spring容器中没有注入PersionService类型的bean
//正常来说我们在这里是获取不到beanName呢。但是事实我们获取到了,看下面我们对getBeanNamesForType的分析
String[] candidateNames = this.getBeanNamesForType(requiredType);
String[] var6;
int var7;
int var8;
String beanName;
if (candidateNames.length > 1) {
List<String> autowireCandidates = new ArrayList(candidateNames.length);
var6 = candidateNames;
var7 = candidateNames.length;
for(var8 = 0; var8 < var7; ++var8) {
beanName = var6[var8];
if (!this.containsBeanDefinition(beanName) || this.getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (!autowireCandidates.isEmpty()) {
candidateNames = StringUtils.toStringArray(autowireCandidates);
}
}
if (candidateNames.length == 1) {
String beanName = candidateNames[0];
//这块逻辑是封装NamedBeanHolder的,对应我们的代码beanName为MyFactoryBean,beanInstance为PersionService,跟进去看看代码流程,我们会在下篇内容说。
return new NamedBeanHolder(beanName, this.getBean(beanName, requiredType.toClass(), args));
} else {
if (candidateNames.length > 1) {
Map<String, Object> candidates = new LinkedHashMap(candidateNames.length);
var6 = candidateNames;
var7 = candidateNames.length;
for(var8 = 0; var8 < var7; ++var8) {
beanName = var6[var8];
if (this.containsSingleton(beanName) && args == null) {
Object beanInstance = this.getBean(beanName);
candidates.put(beanName, beanInstance instanceof NullBean ? null : beanInstance);
} else {
candidates.put(beanName, this.getType(beanName));
}
}
String candidateName = this.determinePrimaryCandidate(candidates, requiredType.toClass());
if (candidateName == null) {
candidateName = this.determineHighestPriorityCandidate(candidates, requiredType.toClass());
}
if (candidateName != null) {
Object beanInstance = candidates.get(candidateName);
if (beanInstance == null || beanInstance instanceof Class) {
beanInstance = this.getBean(candidateName, requiredType.toClass(), args);
}
return new NamedBeanHolder(candidateName, beanInstance);
}
if (!nonUniqueAsNull) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
}
}
return null;
}
}
getBeanNamesForType()
public String[] getBeanNamesForType(ResolvableType type) {
return this.getBeanNamesForType(type, true, true);
}
public String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
Class<?> resolved = type.resolve();
return resolved != null && !type.hasGenerics() ? this.getBeanNamesForType(resolved, includeNonSingletons, allowEagerInit) : this.doGetBeanNamesForType(type, includeNonSingletons, allowEagerInit);
}
public String[] getBeanNamesForType(@Nullable Class<?> type) {
return this.getBeanNamesForType(type, true, true);
}
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
if (this.isConfigurationFrozen() && type != null && allowEagerInit) {
Map<Class<?>, String[]> cache = includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType;
String[] resolvedBeanNames = (String[])cache.get(type);
if (resolvedBeanNames != null) {
return resolvedBeanNames;
} else {
//我们看这里的调用
resolvedBeanNames = this.doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
if (ClassUtils.isCacheSafe(type, this.getBeanClassLoader())) {
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
} else {
return this.doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
}
继续看上面代码块的doGetBeanNamesForType()
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList();
//循环所有的beanName 这个是在Spring容器启动解析Bean的时候放入到这个List中的
Iterator var5 = this.beanDefinitionNames.iterator();
while(true) {
String beanName;
do {
if (!var5.hasNext()) {
var5 = this.manualSingletonNames.iterator();
while(var5.hasNext()) {
beanName = (String)var5.next();
try {
if (this.isFactoryBean(beanName)) {
if ((includeNonSingletons || this.isSingleton(beanName)) && this.isTypeMatch(beanName, type)) {
result.add(beanName);
continue;
}
beanName = "&" + beanName;
}
//我们需要重点关注的是isTypeMatch这个方法 ,如果isTypeMatch这个方法返回true的话,我们会把这个beanName即 MyFactoryBean 放入到result中返回
//我们接着看isTypeMatch方法
if (this.isTypeMatch(beanName, type)) {
result.add(beanName);
}
} catch (NoSuchBeanDefinitionException var13) {
this.logger.trace(LogMessage.format("Failed to check manually registered singleton with name '%s'", beanName), var13);
}
}
return StringUtils.toStringArray(result);
}
beanName = (String)var5.next();
} while(this.isAlias(beanName));
try {
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
if (!mbd.isAbstract() && (allowEagerInit || (mbd.hasBeanClass() || !mbd.isLazyInit() || this.isAllowEagerClassLoading()) && !this.requiresEagerInitForType(mbd.getFactoryBeanName()))) {
boolean isFactoryBean = this.isFactoryBean(beanName, mbd);
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
boolean matchFound = false;
boolean allowFactoryBeanInit = allowEagerInit || this.containsSingleton(beanName);
boolean isNonLazyDecorated = dbd != null && !mbd.isLazyInit();
if (!isFactoryBean) {
if (includeNonSingletons || this.isSingleton(beanName, mbd, dbd)) {
matchFound = this.isTypeMatch(beanName, type, allowFactoryBeanInit);
}
} else {
if (includeNonSingletons || isNonLazyDecorated || allowFactoryBeanInit && this.isSingleton(beanName, mbd, dbd)) {
matchFound = this.isTypeMatch(beanName, type, allowFactoryBeanInit);
}
if (!matchFound) {
beanName = "&" + beanName;
matchFound = this.isTypeMatch(beanName, type, allowFactoryBeanInit);
}
}
if (matchFound) {
result.add(beanName);
}
}
} catch (BeanDefinitionStoreException | CannotLoadBeanClassException var14) {
if (allowEagerInit) {
throw var14;
}
LogMessage message = var14 instanceof CannotLoadBeanClassException ? LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) : LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName);
this.logger.trace(message, var14);
this.onSuppressedException(var14);
} catch (NoSuchBeanDefinitionException var15) {
}
}
}
isTypeMatch()
protected boolean isTypeMatch(String name, ResolvableType typeToMatch, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
String beanName = this.transformedBeanName(name);
boolean isFactoryDereference = BeanFactoryUtils.isFactoryDereference(name);
//因为我们这里是用的AbstractApplicationContext的子类来从Spring容器中获取Bean
//获取beanName为MyFactoryBean的Bean实例 这里是可以获取到Bean实例的
Object beanInstance = this.getSingleton(beanName, false);
if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
//MyFactoryBean是FactoryBean的一个实现类
if (beanInstance instanceof FactoryBean) {
if (isFactoryDereference) {
return typeToMatch.isInstance(beanInstance);
} else {
//这里就是从MyFactoryBean中获取type类型,调用了MyFactoryBean的getObjectType方法,返回的是PersionService.class类型
Class<?> type = this.getTypeForFactoryBean((FactoryBean)beanInstance);
//typeToMatch是我们传入的PersionService.class与MyFactoryBean的getObjectType返回的PersionService.class去比较,那必然返回true;
return type != null && typeToMatch.isAssignableFrom(type);
}
} else {
if (!isFactoryDereference) {
if (typeToMatch.isInstance(beanInstance)) {
return true;
}
if (typeToMatch.hasGenerics() && this.containsBeanDefinition(beanName)) {
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
Class<?> targetType = mbd.getTargetType();
if (targetType != null && targetType != ClassUtils.getUserClass(beanInstance)) {
Class<?> classToMatch = typeToMatch.resolve();
if (classToMatch != null && !classToMatch.isInstance(beanInstance)) {
return false;
}
if (typeToMatch.isAssignableFrom(targetType)) {
return true;
}
}
ResolvableType resolvableType = mbd.targetType;
if (resolvableType == null) {
resolvableType = mbd.factoryMethodReturnType;
}
return resolvableType != null && typeToMatch.isAssignableFrom(resolvableType);
}
}
return false;
}
} else if (this.containsSingleton(beanName) && !this.containsBeanDefinition(beanName)) {
return false;
} else {
BeanFactory parentBeanFactory = this.getParentBeanFactory();
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
return parentBeanFactory.isTypeMatch(this.originalBeanName(name), typeToMatch);
} else {
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
Class<?> classToMatch = typeToMatch.resolve();
if (classToMatch == null) {
classToMatch = FactoryBean.class;
}
Class<?>[] typesToMatch = FactoryBean.class == classToMatch ? new Class[]{classToMatch} : new Class[]{FactoryBean.class, classToMatch};
Class<?> predictedType = null;
if (!isFactoryDereference && dbd != null && this.isFactoryBean(beanName, mbd) && (!mbd.isLazyInit() || allowFactoryBeanInit)) {
RootBeanDefinition tbd = this.getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
Class<?> targetType = this.predictBeanType(dbd.getBeanName(), tbd, typesToMatch);
if (targetType != null && !FactoryBean.class.isAssignableFrom(targetType)) {
predictedType = targetType;
}
}
if (predictedType == null) {
predictedType = this.predictBeanType(beanName, mbd, typesToMatch);
if (predictedType == null) {
return false;
}
}
ResolvableType beanType = null;
if (FactoryBean.class.isAssignableFrom(predictedType)) {
if (beanInstance == null && !isFactoryDereference) {
beanType = this.getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit);
predictedType = beanType.resolve();
if (predictedType == null) {
return false;
}
}
} else if (isFactoryDereference) {
predictedType = this.predictBeanType(beanName, mbd, FactoryBean.class);
if (predictedType == null || !FactoryBean.class.isAssignableFrom(predictedType)) {
return false;
}
}
if (beanType == null) {
ResolvableType definedType = mbd.targetType;
if (definedType == null) {
definedType = mbd.factoryMethodReturnType;
}
if (definedType != null && definedType.resolve() == predictedType) {
beanType = definedType;
}
}
return beanType != null ? typeToMatch.isAssignableFrom(beanType) : typeToMatch.isAssignableFrom(predictedType);
}
}
}
总结
- 我们在调用MyFactoryBean的getObjectType方法的时候,获取到的值为:PersionService和我们传入的type是一样的类型。所以这里返回true,根据我们上面说的如果isTypeMatch返回true的话,我们返回的beanName为MyFactoryBean
- 我们调用getBean(Class requiredType)方法根据类型来获取容器中的bean的时候,对应我们的例子就是:根据类型PersionService来从Spring容器中获取Bean(首先明确的一点是在Spring容器中没有PersionService类型的BeanDefinition)
- Spring在根据type去获取Bean的时候,会先获取到beanName(即MyFactoryBean)。获取beanName的过程是:先循环Spring容器中的所有的beanName,然后根据beanName获取对应的BeanDefinition,如果当前bean是FactoryBean的类型,则会从Spring容器中根据beanName获取对应的Bean实例,接着调用获取到的Bean实例的getObjectType方法获取到Class类型,判断此Class类型和我们传入的Class是否是同一类型。如果是则返回测beanName,对应到我们这里就是:根据MyFactoryBean获取到MyFactoryBean实例,调用MyFactoryBean的getObjectType方法获取到返回值PersionService.class。和我们传入的类型一致,所以这里获取的beanName为MyFactoryBean。
- 我们分析中有NamedBeanHolder这个类,其中beanName是MyFactoryBean,beanInstance为PersionService,这一点很重要。