【Spring源码系列】——彻底搞懂FactoryBean

       在上篇博客中【源码Spring系列】——彻底搞懂BeanFactory和FactoryBean不同讲解了两者的不同,先确定两者的作用并不一样,本文主要讲解Spring是怎样从FactoryBean获取我们自己创建的Bean实例。

何为FactoryBean?

public interface FactoryBean {
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class getObjectType();

    default boolean isSingleton() {
        return true;
    }
}

从上述代码的定义中可以发现FactoryBean中定义了一个Spring Bean重要的三个特性:是否单例,Bean类型,Bean实例。也证明了FactoryBean本身就是一个Bean。下面写一个关于FactoryBean的应用,在从源码角度解析Spring容器是如何从FactoryBean中获取创建的Bean实例。

public class User {

    public User() {
        System.out.println("调用构造器User()");
    }

    public void testUser() {
        System.out.println("user类被调用了");
    }
}


@Component
public class MyFactoryBean implements FactoryBean {
   @Override
   public Object getObject() throws Exception {
      return new User();
   }

   @Override
   public Class getObjectType() {
      return User.class;
   }
}

@Service
public class UserService {
    @Autowired
    private User user;


    public UserService(){
        System.out.println("调用构造器UserService()");
    }

    public User getUser() {
        return user;
    }
}

@ComponentScan("mandy.com")
@Configuration
public class AppConfig {

}

@Test
    public void test(){

        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        User user = context.getBean(User.class);
        user.testUser();
        System.out.println(context.getBean("userService"));
        UserService userService = (UserService) context.getBean("userService");
        System.out.println(userService.getUser());
    }

【Spring源码系列】——彻底搞懂FactoryBean_第1张图片

从上述代码以及打印结果中可以知道,我们从Spring容器中获得了User类型的Bean,并且成功注入到UserService中。那么这个获取Bean的过程,以及注入Bean的过程在Spring容器中是怎么处理的呢?

org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class)

    public  T getBean(Class requiredType) throws BeansException {
        return this.getBean(requiredType, (Object[])null);
    }

    public  T getBean(Class requiredType, @Nullable Object... args) throws BeansException {
        Assert.notNull(requiredType, "Required type must not be null");
        //解析bean
        Object resolved = this.resolveBean(ResolvableType.forRawClass(requiredType), args, false);
        if (resolved == null) {
            throw new NoSuchBeanDefinitionException(requiredType);
        } else {
            return resolved;
        }
    }
   @Nullable
    private  T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
        //关键点 根据传入的Class类型来获取BeanName
        NamedBeanHolder namedBean = this.resolveNamedBean(requiredType, args, nonUniqueAsNull);
        if (namedBean != null) {
            return namedBean.getBeanInstance();
        } else {
            //如果当前Spring容器中没有获取到相应的Bean信息,则从父容器中获取
            //SpringMVC是一个很典型的父子容器
            BeanFactory parent = this.getParentBeanFactory();
            if (parent instanceof DefaultListableBeanFactory) {
                return ((DefaultListableBeanFactory)parent).resolveBean(requiredType, args, nonUniqueAsNull);
            } else if (parent != null) {
                ObjectProvider parentProvider = parent.getBeanProvider(requiredType);
                if (args != null) {
                    return parentProvider.getObject(args);
                } else {
                    return nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable();
                }
            } else {
                return null;
            }
        }
    }
    

重点关注org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveNamedBean(org.springframework.core.ResolvableType, java.lang.Object[], boolean)

    @Nullable
	private  NamedBeanHolder resolveNamedBean(
			ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {

		Assert.notNull(requiredType, "Required type must not be null");
        //我们调用getBean方法传入的是mandy.com.bean.User类型,但是并没有在Spring容器中注入User类型的Bean
        //理论上是获取不到beanName的,但是通过getBeanNamesForType却拿到了
		String[] candidateNames = getBeanNamesForType(requiredType);
        //如果有多个BeanName,则挑选合适的BeanName
		if (candidateNames.length > 1) {
			List 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中
		if (candidateNames.length == 1) {
			String beanName = candidateNames[0];
			return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
		}
		else if (candidateNames.length > 1) {
            //如果合适的BeanName还是有多个的话
			Map 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));
				}
			}
			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;
	}

 怎么从org.springframework.beans.factory.support.DefaultListableBeanFactory#getBeanNamesForType(org.springframework.core.ResolvableType)中获取到的beanName呢?

    @Override
	public String[] getBeanNamesForType(@Nullable Class type, boolean includeNonSingletons, boolean allowEagerInit) {
		if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
			return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
		}
        //先从缓存中获取
		Map, 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())) {
            //这里对应到我们这里 key是User Value是MyFactoryBean
			cache.put(type, resolvedBeanNames);
		}
		return resolvedBeanNames;
	}

咱们今天先不看doGetBeanNamesForType方法,咱们看下allBeanNamesByType

private final Map, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

getObject()  bean  singletonObjects myFactoryBean

getObjectType()  User.class--映射--myFactoryBean

allBeanNamesByType: User.class:myFactoryBean   factoryBeanObjectCache

【Spring源码系列】——彻底搞懂FactoryBean_第2张图片

 

 

allBeanNamesByType 就是FactoryBean按bean类型存储的Map,使得类可以通过getObjectType() 被找到。

这也就是factoryBeanObjectCache,与allBeanNamesByType的关系

你可能感兴趣的:(【源码Spring系列】,Factory)