其实就是调用了FactoryBean的getObject()返回该bean的。
通过上面Spring-FactoryBean的源码——简略解析(上)_快撑死的鱼的博客-CSDN博客的分析,WebServiceFactoryBean是一个FactoryBean,
getBean("&webServiceFactoryBean"),此时spring中会创建一个WebServiceFactoryBean实例,而且返回也是WebServiceFactoryBean实例本身。因此spring容器还利用不到WebServiceFactoryBean的getObject()来返回WebService相关实例。
那么spring是在什么时候去调用getBean("webServiceFactoryBean"),然后利用WebServiceFactoryBean的getObject()来返回WebServiceWrapper的呢?
我们仅仅知道的是TestController依赖了WebService,根据前面提到spring托管bean的流程,TestController在依赖注入的时候,一定会找到WebServiceWrapper!!!下面我们根据这个思路去debug分析下源码:
下面看下TestController的依赖注入阶段:
- protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- throws BeanCreat BeanWrapper instanceWrapper = null;
-
-
- // Initialize the bean instance.
- Object exposedObject = bean;
- try {
- populateBean(beanName, mbd, instanceWrapper);
- exposedObject = initializeBean(beanName, exposedObject, mbd);
- }
- }
一个bean依赖注入的入口方法就是populateBean():
- protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
-
- for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
- PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
- }
- }
InstantiationAwareBeanPostProcessor 是一个bean的实例化处理接口,
postProcessProperties()主要目的是对实例的属性进行处理。
其中有一个实现类:AutowiredAnnotationBeanPostProcessor就是用来实现依赖注入的。大概看下该类上的注释和构造器:
- /**
- 自动连接注释字段、setter方法和任意配置方法的BeanPostProcessor实现。这些要注入的成员是通过注释检测的:默认情况下,是Spring的@Autowired和@Value注释。
- 还支持JSR-330的@Inject注释(如果可用的话),作为Spring自己的@Autowired的直接替代。
- */
-
- public AutowiredAnnotationBeanPostProcessor() {
- this.autowiredAnnotationTypes.add(Autowired.class);
- this.autowiredAnnotationTypes.add(Value.class);
- try {
- this.autowiredAnnotationTypes.add((Class extends Annotation>)
- ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
- logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
- }
- catch (ClassNotFoundException ex) {
- // JSR-330 API not available - simply skip.
- }
- }
其实就是我们项目中使用的@Autowired,@Value等注入的实现方式。autowiredAnnotationTypes指定了支持哪些注解。
下面看下AutowiredAnnotationBeanPostProcessor的postProcessProperties():
- public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
- // 找到需要注入的字段
- InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
- try {
- // 对每个字段进行注入
- metadata.inject(bean, beanName, pvs);
- }
- catch (BeanCreationException ex) {
- throw ex;
- }
- catch (Throwable ex) {
- throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
- }
- return pvs;
- }
-
- public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
- Collection
checkedElements = this.checkedElements; - Collection
elementsToIterate = - (checkedElements != null ? checkedElements : this.injectedElements);
- if (!elementsToIterate.isEmpty()) {
- for (InjectedElement element : elementsToIterate) {
- // 对每个依赖字段进行注入
- element.inject(target, beanName, pvs);
- }
- }
- }
对于TestController来说,只有一个WebService字段需要注入,因此会只有一个InjectedElement要进行inject。InjectedElement有两个实现类AutowiredFieldElement和AutowiredMethodElement。由于我们这里是字段注入,所以看看AutowiredFieldElement的inject();
- protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
- // 当前要注入的字段是什么
- Field field = (Field) this.member;
- // 给该字段赋值的值到底是什么?
- Object value;
- if (this.cached) {
- try {
- value = resolvedCachedArgument(beanName, this.cachedFieldValue);
- }
- catch (NoSuchBeanDefinitionException ex) {
- // Unexpected removal of target bean for cached argument -> re-resolve
- value = resolveFieldValue(field, bean, beanName);
- }
- }
- else {
- // 根据该字段信息,解析出value
- value = resolveFieldValue(field, bean, beanName);
- }
- if (value != null) {
- // 如果解析出来的值不为空,那么就进行赋值
- ReflectionUtils.makeAccessible(field);
- field.set(bean, value);
- }
- }
doResolveDependency()方法中,有个关键点,那就java的Field提供了当前Field的java类型是什么。spring利用了这一点,然后根据类型去找到候选者!!!
此时type=WebService.class
一路debug,在findAutowireCandidates()方法中,发现candidateNames中出现了,webServiceFactoryBean,也就是说spring把webServiceFactoryBean当作了一个WebService.其实大概测试也知道是因为WebServiceFactoryBean的getObjectType()返回了WebService.class和要依赖注入的字段相匹配。
因此关键的代码是:
- public static String[] beanNamesForTypeIncludingAncestors(
- ListableBeanFactory lbf, Class> type, boolean includeNonSingletons, boolean allowEagerInit) {
- // 根据WebService.class去找到候选者的bean
- String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
- }
-
- @Override
- public String[] getBeanNamesForType(@Nullable Class> type, boolean includeNonSingletons, boolean allowEagerInit) {
- String[] resolvedBeanNames = cache.get(type);
- if (resolvedBeanNames != null) {
- return resolvedBeanNames;
- }
- resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
-
- return resolvedBeanNames;
- }
-
- private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
- List
result = new ArrayList<>(); -
- // Check all bean definitions.
- for (String beanName : this.beanDefinitionNames) {
- 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)) {
- matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
- }
- }
- else {
- if (includeNonSingletons || isNonLazyDecorated ||
- (allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
- matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
- }
- if (!matchFound) {
- // In case of FactoryBean, try to match FactoryBean instance itself next.
- beanName = FACTORY_BEAN_PREFIX + beanName;
- if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
- matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
- }
- }
- }
- if (matchFound) {
- result.add(beanName);
- }
-
- }
-
-
- }
-
- protected boolean isTypeMatch(String name, ResolvableType typeToMatch, boolean allowFactoryBeanInit)
- throws NoSuchBeanDefinitionException {
-
- if (beanInstance instanceof FactoryBean) {
- if (!isFactoryDereference) {
- Class> type = getTypeForFactoryBean((FactoryBean>) beanInstance);
- return (type != null && typeToMatch.isAssignableFrom(type));
- }
- else {
- return typeToMatch.isInstance(beanInstance);
- }
- }
-
- }
-
- protected Class> getTypeForFactoryBean(FactoryBean> factoryBean) {
- try {
- if (System.getSecurityManager() != null) {
- return AccessController.doPrivileged(
- (PrivilegedAction
>) factoryBean::getObjectType, getAccessControlContext()); - }
- else {
- 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;
- }
- }
在匹配的过程中,如果一个bean是FactoryBean,那么就去检查它的getObjectType()返回的类型是否匹配。对于TestController来说,它的成员字段webService是WebService类型,于是spring会去容器中找,恰好WebServiceFactoryBean的getObjectType()返回就是WebService类型,于是匹配。
在上面doResolveDependency()中的 findAutowireCandidates()返回了一个WebServiceFactoryBean作为匹配的bean,但是还并没有返回需要注入的value,下面接着看doResolveDependency()
- public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
- @Nullable Set
autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { - String autowiredBeanName;
- Object instanceCandidate;
- String autowiredBeanName;
- Object instanceCandidate;
-
- if (matchingBeans.size() > 1) {
- autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
- if (autowiredBeanName == null) {
- if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
- return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
- }
- else {
- // In case of an optional Collection/Map, silently ignore a non-unique case:
- // possibly it was meant to be an empty collection of multiple regular beans
- // (before 4.3 in particular when we didn't even look for collection beans).
- return null;
- }
- }
- instanceCandidate = matchingBeans.get(autowiredBeanName);
- }
- else {
- // We have exactly one match.
- Map.Entry
entry = matchingBeans.entrySet().iterator().next(); - autowiredBeanName = entry.getKey();
- instanceCandidate = entry.getValue();
- }
-
- if (autowiredBeanNames != null) {
- autowiredBeanNames.add(autowiredBeanName);
- }
- if (instanceCandidate instanceof Class) {
- instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
- }
- Object result = instanceCandidate;
- return result;
- }
matchingBeans 目前的只包含一个key-value,其中key是webServiceFactoryBean,value则是WebServiceFactoryBean.class。因此真正的value是来自于上面的
descriptor.resolveCandidate()方法:
- public Object resolveCandidate(String beanName, Class> requiredType, BeanFactory beanFactory)
- throws BeansException {
-
- return beanFactory.getBean(beanName);
- }
这里注意到到,传入的beanName是webServiceFactoryBean!!!这一下子联想到前面说的,spring对于获取FactoryBean本身必须要对beanName加一个特殊的前缀。否则。。。否则就不是返回它自己啦,不用跟踪源码,我们也能够大概猜得到,对于FactoryBean如果beanName不加特殊前缀返回的bean,是调用FactoryBean的getObject()方法返回的!!!结合前面的源码,确实如此。到此FactoryBean的实现原理分析结束。