在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的实现原理分析结束。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。