Spring源码解析 - FactoryBean&&BeanFactory
何时使用FactoryBean?
FactoryBean是一个工厂Bean,可生成某一个类型的Bean实例。
最大作用:让我们能够自定义Bean的创建过程。
而在BeanFactory中可创建和管理Spring容器中的Bean,它对Bean的创建有一个统一的流程。
1 FactoryBean
定义
- 泛型接口
API
-
返回Bean对象实例
-
Bean类型
-
是否单例。true是单例,false是非单例 。在Spring5.x利用Java8新特性变成default方法,返回true
2 使用FactoryBean
//FactoryBean接口实现类
@Component
public class FactoryBeanLearn implements FactoryBean { @Override public Object getObject() throws Exception { // 自己new,这里就可以控制Bean的创建过程 return new FactoryBeanServiceImpl(); } @Override public Class<?> getObjectType() { return FactoryBeanService.class; } @Override public boolean isSingleton() { return true; }
}
接口
public interface FactoryBeanService { /** * 测试FactoryBean */ void testFactoryBean();
}
//实现类
public class FactoryBeanServiceImpl implements FactoryBeanService { @Override public void testFactoryBean() { System.out.println("我是FactoryBean的一个测试类。。。。"); }
}
测试类
@Test
public void test() { ClassPathXmlApplicationContext cac = new ClassPathXmlApplicationContext("classpath:com/javaedge/applicationContext.xml"); FactoryBeanService beanService = cac.getBean(FactoryBeanService.class); beanService.testFactoryBean(); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
从Spring容器中获取了FactoryBeanService类型的Bean。那么这个获取Bean的过程Spring是怎么处理的呢?它是怎么从FactoryBean中获取我们自己创建的Bean实例的呢?
先从getBean这个方法看起,在Spring的AbstractApplicationContext中有很多重载的getBean方法,这里调用根据Type(Class类型)来获取的Bean信息。我们传入type是FactoryBeanService类型。
getBean
AbstractApplicationContext#getBean(java.lang.Class)
DefaultListableBeanFactory#getBean(java.lang.Class)
resolveBean
@Nullable
private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
// 解析Bean
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
if (namedBean != null) { return namedBean.getBeanInstance();
}
// 如果当前Spring容器中没获取到对应Bean信息,则从父容器获取
BeanFactory parent = 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()); }
}
return null;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
关注的是resolveNamedBean方法:
@SuppressWarnings("unchecked")
@Nullable
private <T> NamedBeanHolder<T> resolveNamedBean( ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException { Assert.notNull(requiredType, "Required type must not be null");
String[] candidateNames = getBeanNamesForType(requiredType); if (candidateNames.length > 1) { List<String> autowireCandidates = new ArrayList<>(candidateNames.length); for (String beanName : candidateNames) { if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) { autowireCandidates.add(beanName); } } if (!autowireCandidates.isEmpty()) { candidateNames = StringUtils.toStringArray(autowireCandidates); }
} if (candidateNames.length == 1) { String beanName = candidateNames[0]; return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
}
else if (candidateNames.length > 1) { Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length); for (String beanName : candidateNames) { if (containsSingleton(beanName) && args == null) { Object beanInstance = getBean(beanName); candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance)); } else { candidates.put(beanName, getType(beanName)); } } String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass()); if (candidateName == null) { candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass()); } if (candidateName != null) { Object beanInstance = candidates.get(candidateName); if (beanInstance == null || beanInstance instanceof Class) { beanInstance = getBean(candidateName, requiredType.toClass(), args); } return new NamedBeanHolder<>(candidateName, (T) beanInstance); } if (!nonUniqueAsNull) { throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet()); }
} return null;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
@SuppressWarnings("unchecked")
@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为com.javaedge.FactoryBeanService类型,但没有在Spring容器中注入FactoryBeanService类型的Bean
// 所以讲道理在这里应该获取不到beanName,事实是这样吗?看对getBeanNamesForType的分析
String[] candidateNames = getBeanNamesForType(requiredType);
// 有多个BeanName,则挑最合适的
if (candidateNames.length > 1) { List<String> autowireCandidates = new ArrayList<>(candidateNames.length); for (String beanName : candidateNames) { if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) { autowireCandidates.add(beanName); } } if (!autowireCandidates.isEmpty()) { candidateNames = StringUtils.toStringArray(autowireCandidates); }
} // 如果只有一个BeanName,调用getBean获取Bean实例放到NamedBeanHolder
// todo
if (candidateNames.length == 1) { String beanName = candidateNames[0]; return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
}
// 经过挑选后,如果合适的BeanName还是多个
else if (candidateNames.length > 1) { Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length); for (String beanName : candidateNames) { // 看看是不是已经创建过的单例Bean if (containsSingleton(beanName) && args == null) { Object beanInstance = getBean(beanName); candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance)); } else { // 调用getType继续获取Bean实例 candidates.put(beanName, getType(beanName)); } } // 有多个Bean实例,则取带有Primary注解或者带有Primary信息的 String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass()); if (candidateName == null) { // 如果没有Primary注解或者Primary相关的信息,则取优先级高的Bean candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass()); } if (candidateName != null) { Object beanInstance = candidates.get(candidateName); // Class类型的话 继续调用getBean获取Bean实例 if (beanInstance == null || beanInstance instanceof Class) { beanInstance = getBean(candidateName, requiredType.toClass(), args); } return new NamedBeanHolder<>(candidateName, (T) beanInstance); } if (!nonUniqueAsNull) { // 都没获取到,抛出异常 throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet()); }
} return null;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
上面的代码中我们传入的type是com.javaedge.FactoryBeanService类型,但是在我们的Spring容器中却没有FactoryBeanService类型的Bean,那么我们是怎么从getBeanNamesForType获取到beanName的?
getBeanNamesForType
@Override
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
if (!isConfigurationFrozen() || type == null || !allowEagerInit) { return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
// 先从缓存获取
Map<Class<?>, String[]> cache = (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
String[] resolvedBeanNames = cache.get(type);
if (resolvedBeanNames != null) { return resolvedBeanNames;
}
// 调用doGetBeanNamesForType获取beanName
resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
// 所传入类能否被当前类加载所加载
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) { // 放到缓存,解析一次后从缓存中获取 // 这里对应到我们这里 K:FactoryBeanService,V:beanFactoryLearn cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
doGetBeanNamesForType
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList<>(); // 循环所有beanName,这个是在Spring容器启动解析Bean的时候放入到这个List中的
// 校验所有 bean definitions
for (String beanName : this.beanDefinitionNames) { // Only consider bean as eligible if the bean name is not defined as alias for some other bean. // 如果未将 bean name 定义为其他bean的别名,则仅将bean视为可选 if (!isAlias(beanName)) { try { // 根据 beanName 获取 RootBeanDefinition RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // Only check bean definition if it is complete. // RootBeanDefinition 的 Bean 不是抽象类、非延迟初始化 if (!mbd.isAbstract() && (allowEagerInit || (mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) && !requiresEagerInitForType(mbd.getFactoryBeanName()))) { // 是否为 FactoryBean 的子类 boolean isFactoryBean = isFactoryBean(beanName, mbd); BeanDefinitionHolder dbd = mbd.getDecoratedDefinition(); boolean matchFound = false; boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName)); boolean isNonLazyDecorated = (dbd != null && !mbd.isLazyInit()); if (!isFactoryBean) { if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) { // 如果isTypeMatch返回true,则把这个beanName即 factoryBeanLearn 放入到result中返回 matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit); } } else { if (includeNonSingletons || isNonLazyDecorated || (allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) { matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit); } if (!matchFound) { // 如果不匹配,还是FactoryBean的子类 这里会把beanName变为 &beanName // In case of FactoryBean, try to match FactoryBean instance itself next. beanName = FACTORY_BEAN_PREFIX + beanName; matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit); } } if (matchFound) { result.add(beanName); } } } catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) { if (allowEagerInit) { throw ex; } // Probably a placeholder: let's ignore it for type matching purposes. LogMessage message = (ex instanceof CannotLoadBeanClassException ? LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) : LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName)); logger.trace(message, ex); // Register exception, in case the bean was accidentally unresolvable. onSuppressedException(ex); } }
} // 这里的Bean是Spring容器创建的特殊的几种Bean ,如Environment
// Check manually registered singletons too.
for (String beanName : this.manualSingletonNames) { try { // In case of FactoryBean, match object created by FactoryBean. if (isFactoryBean(beanName)) { if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) { result.add(beanName); // Match found for this bean: do not match FactoryBean itself anymore. continue; } // In case of FactoryBean, try to match FactoryBean itself next. beanName = FACTORY_BEAN_PREFIX + beanName; } // Match raw bean instance (might be raw FactoryBean). if (isTypeMatch(beanName, type)) { result.add(beanName); } } catch (NoSuchBeanDefinitionException ex) { // Shouldn't happen - probably a result of circular reference resolution... logger.trace(LogMessage.format( "Failed to check manually registered singleton with name '%s'", beanName), ex); }
} return StringUtils.toStringArray(result);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
FactoryBeanLearn是FactoryBean类型的,所以上面代码中会调用isTypeMatch判断FactoryBeanLearn是不是和传入类型匹配。这里是值:FactoryBeanService类。
isTypeMatch
类型匹配判断
protected boolean isTypeMatch(String name, ResolvableType typeToMatch, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException { // 转换beanName,我们的beanName为factoryBeanLearn 因为上面循环了Spring容器中的所有的Bean
String beanName = transformedBeanName(name);
boolean isFactoryDereference = BeanFactoryUtils.isFactoryDereference(name); // 因为我们这里是用的AbstractApplicationContext的子类从Spring容器获取Bean
// 获取beanName为factoryBeanLearn的Bean实例,这里是可以获取到Bean实例的
// Check manually registered singletons.
Object beanInstance = getSingleton(beanName, false);
if (beanInstance != null && beanInstance.getClass() != NullBean.class) { // factoryBeanLearn是FactoryBean的实现类 if (beanInstance instanceof FactoryBean) { // 判断beanName是不是&开头,这里明显不是 if (!isFactoryDereference) { // 从factoryBeanLearn中获取type类型 Class<?> type = getTypeForFactoryBean((FactoryBean<?>) beanInstance); // 从factoryBeanLearn中获取到的type类型和传入类型是否一致,是则返回 return (type != null && typeToMatch.isAssignableFrom(type)); } ...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
getTypeForFactoryBean
@Nullable
protected Class<?> getTypeForFactoryBean(FactoryBean<?> factoryBean) {
try { if (System.getSecurityManager() != null) { return AccessController.doPrivileged( (PrivilegedAction<Class<?>>) factoryBean::getObjectType, getAccessControlContext()); } else { // 调用FactoryBean实例的getObjectType()方法 return factoryBean.getObjectType(); }
}
catch (Throwable ex) { // Thrown from the FactoryBean's getObjectType implementation. logger.info("FactoryBean threw exception from getObjectType, despite the contract saying " + "that it should return null if the type of its object cannot be determined yet", ex); return null;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
在调用factoryBeanLearn的getObjectType方法时,获取到的值为:com.javaedge.FactoryBeanService和我们传入type是一样的类型。所以这里返回true,根据我们上面说的如果isTypeMatch返回true的话,我们返回的beanName为factoryBeanLearn。
调用getBean(Class requiredType)方法根据类型获取容器中bean时
对应例子就是:根据类型FactoryBeanService从Spring容器中获取Bean(Spring容器中没有FactoryBeanService类型的BeanDefinition,但有一个Bean和FactoryBeanService这个类型有一些关系)。
Spring在根据type去获取Bean的时候,会先获取到beanName。
获取beanName的过程
先循环Spring容器中的所有的beanName
然后根据beanName获取对应的BeanDefinition,如果当前bean是FactoryBean的类型,则会从Spring容器中根据beanName获取对应的Bean实例,接着调用获取到的Bean实例的getObjectType方法获取到Class类型,判断此Class类型和我们传入的Class是否是同一类型。如果是则返回测beanName,对应到我们这里就是:根据factoryBeanLearn获取到FactoryBeanLearn实例,调用FactoryBeanLearn的getObjectType方法获取到返回值FactoryBeanService.class。和我们传入的类型一致,所以这里获取的beanName为factoryBeanLearn。
换句话说这里我们把factoryBeanLearn这个beanName映射为了:FactoryBeanService类型。即FactoryBeanService类型对应的beanName为factoryBeanLearn这是很重要的一点。
文章来源: javaedge.blog.csdn.net,作者:JavaEdge.,版权归原作者所有,如需转载,请联系作者。
原文链接:javaedge.blog.csdn.net/article/details/107457279
- 点赞
- 收藏
- 关注作者
评论(0)