关于spring:SpringFactoryBean源码简略分析

4次阅读

共计 16331 个字符,预计需要花费 41 分钟才能阅读完成。

在 spring 中,如果一个 bean 的创立过程很简单,咱们能够应用 FactoryBean。
比方像上面的状况,我定义一套 webService 框架。

public interface WebService {void service();  
}

public class DefaultWebService implements WebService {
    private String serviceName;

    public DefaultWebService(String serviceName) {this.serviceName = serviceName;}

    @Override
    public void service() {System.out.println(serviceName + ": current support service  for  you....");
    }
}

public class WebServiceWrapper implements WebService {
    private WebService webService;
    public WebServiceWrapper(WebService webService) {this.webService = webService;}

    @Override
    public void service() {System.out.println("befor service, we need do something....");
        webService.service();}
}

WebService 接口定义服务的规范,DefaultWebService 是一个默认实现,WebServiceWrapper 的次要作用是在理论服务之前,做一些查看,筹备等工作。
因而当咱们应用 WebService,实际上是心愿应用的是 WebServiceWrapper。

当初 webService 框架实现好了,并打包进去了,当初我须要在我的项目中利用应用 spring 注解个性去应用。

那该怎么办呢?我能够实现 spring 提供的 FactoryBean 接口,就像上面这样:

@Component
public class WebServiceFactoryBean implements FactoryBean {

    @Override
    public boolean isSingleton() {return true;}

    @Override
    public Object getObject() throws Exception {return this.createWebService();
    }

    @Override
    public Class<?> getObjectType() {return WebService.class;}

    private Object createWebService() {DefaultWebService webService = new DefaultWebService("Backend Service");
        // create a proxy
        WebServiceWrapper webServiceWrapper = new WebServiceWrapper(webService);
        return webServiceWrapper;
    }
}

紧接着,就能够利用 spring 的性能去应用了

@RestController
public class TestController {
    @Autowired
    private WebService webService;

    @GetMapping(value = "webService")
    public void webService() {webService.service();
    }
}

http://localhost:8080/webService,控制台会输入:
befor service, we need do something….
Backend Service: current support service for you….

通过输入咱们晓得,该 webService,注入的应该是 WebServiceWrapper。
这里的次要疑难是,咱们应用 @Component 托管 spring 的 bean 是 WebServiceFactoryBean。然而最初在 TestController 中,WebServiceWrapper 的相干信息,只有是怎么被注入的呢?也就是 spring 是怎么利用 FactoryBean 来实现特定 bean 工厂的呢?

spring 托管一个 bean 大略的流程是:
bean 信息扫描 -> 实例化 -> 依赖注入 -> 初始化

首先看下 bean 扫描阶段,在所有扫描进去的 BeanDefinition 中,没有发现 WebServiceWrapper 的相干信息,只有 WebServiceFactoryBean 的相干信息。所以 spring 不是在扫描阶段解析出 WebServiceFactoryBean 相干信息的。

再看下 WebServiceFactoryBean 的实例化过程:

    public void preInstantiateSingletons() throws BeansException {
    // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);   
                }
                else {getBean(beanName);
                }
            }
        }
    }

这段源码中,有个判断是说如果以后 bean 是 FactoryBean,那么获取该 FactoryBean 自身时,beanName 要加上一个非凡的前缀“&”。因为 WebServiceFactoryBean 是一个 FactoryBean,所以此时调用的是:Object bean = getBean(FACTORY_BEAN_PREFIX + beanName), 入参是:&webServiceFactoryBean
spring 中 getBean 会去调用 doGetBean():

    protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
            throws BeansException {
// Create bean instance.
                if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {
                        try {return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
}

先创立一个 bean 实例,而后通过 getObjectForBeanInstance()返回一个实例。
这里疑难是,我明明都创立好了一个实例,我间接返回不就好了吗,为什么还要通过 getObjectForBeanInstance()返回呢?上面看看该办法得形容:

/**
获取给定 bean 实例的对象,能够是 bean 实例自身,也能够是 FactoryBean 所创立的对象。*/
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

// 判断 beanName 是否以 FactoryBean "&" 非凡前缀结尾,如果是以 "&" 结尾
// 阐明以后获取的是 FactoryBean 自身
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;}
            return beanInstance;
        }
    // 如果该 bean 不是 FactoryBean 那么间接返回
    if (!(beanInstance instanceof FactoryBean)) {return beanInstance;}

    // 否则就利用 FactoryBean 返回该 bean
    Object object = null;
        if (mbd != null) {mbd.isFactoryBean = true;}
        else {object = getCachedObjectForFactoryBean(beanName);
        }
        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());
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
}

下面的逻辑也是很清晰了,最初看下

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {Object object = doGetObjectFromFactoryBean(factory, beanName);
            if (shouldPostProcess) {
                try {object = postProcessObjectFromFactoryBean(object, beanName);
                }
                catch (Throwable ex) {throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
}

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 {**object = factory.getObject();**
            }
        }
        catch (FactoryBeanNotInitializedException ex) {throw new BeanCurrentlyInCreationException(beanName, ex.toString());
        }
        catch (Throwable ex) {throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
        }

        // Do not accept a null value for a FactoryBean that's not fully
        // initialized yet: Many FactoryBeans just return null then.
        if (object == null) {if (isSingletonCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");
            }
            object = new NullBean();}
        return object;
    }

其实就是调用了 FactoryBean 的 getObject()返回该 bean 的。

通过下面的剖析,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<InjectedElement> checkedElements = this.checkedElements;
        Collection<InjectedElement> 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);
            }
        }

对于 TestController,field 天然是 webService,这里的值,应该是 webService 的一个具体对象,然而显著还没有 cached,因而要进行解析:

    private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
            desc.setContainingClass(bean.getClass());
            Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
            Assert.state(beanFactory != null, "No BeanFactory available");
            TypeConverter typeConverter = beanFactory.getTypeConverter();
            Object value;
            try {value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
            }
return value;
}

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
        if (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);
        }
        else if (ObjectFactory.class == descriptor.getDependencyType() ||
                ObjectProvider.class == descriptor.getDependencyType()) {return new DependencyObjectProvider(descriptor, requestingBeanName);
        }
        else if (javaxInjectProviderClass == descriptor.getDependencyType()) {return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
        }
        else {Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
            if (result == null) {
//  解析 value
                result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
            }
            return result;
        }
    }

    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    // 这里十分要害,实际上就是依据以后 field, 获取它的类型是什么!!!Class<?> type = descriptor.getDependencyType();
// 依据类型去找到对应的候选者
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

}

    protected Map<String, Object> findAutowireCandidates(@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());

}

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<String> 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<Class<?>>) 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<String> 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<String, Object> 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 的实现原理剖析完结。

正文完
 0