先介绍一下Spring的IOC容器到底是个什么东西,都说是一个控制反转的容器,将对象的控制权交给IOC容器,其实在看了源代码之后,就会发现IOC容器只是一个存储单例的一个ConcurrentHashMap<String, BeanDefinition>
BeanDefinition只是一个将Object包装的对象,带有实例的其他属性,比如对应的Class等,而Spring默认创建的IOC容器为new DefaultListableBeanFactory(),可以看一下这个对象的属性
/** Map from serialized id to factory instance. */private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =new ConcurrentHashMap<>(8);/** Optional id for this factory, for serialization purposes. */@Nullableprivate String serializationId;/** Whether to allow re-registration of a different definition with the same name. */private boolean allowBeanDefinitionOverriding = true;/** Whether to allow eager class loading even for lazy-init beans. */private boolean allowEagerClassLoading = true;/** Optional OrderComparator for dependency Lists and arrays. */@Nullableprivate Comparator<Object> dependencyComparator;/** Resolver to use for checking if a bean definition is an autowire candidate. */private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();/** Map from dependency type to corresponding autowired value. */private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);//这个Map就是专门储存实例的/** Map of bean definition objects, keyed by bean name. */private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);/** Map of singleton and non-singleton bean names, keyed by dependency type. */private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);/** Map of singleton-only bean names, keyed by dependency type. */private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);/** List of bean definition names, in registration order. */private volatile List<String> beanDefinitionNames = new ArrayList<>(256);/** List of names of manually registered singletons, in registration order. */private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);/** Cached array of bean definition names in case of frozen configuration. */@Nullableprivate volatile String[] frozenBeanDefinitionNames;/** Whether bean definition metadata may be cached for all beans. */private volatile boolean configurationFrozen = false;
而DefaultListableBeanFactory继承了BeanFactory的接口,并实现的这些方法。
BeanFactory
BeanFactory是Spring最核心的接口,也是Spring中最开始的地方,这个接口定义了一些常用的方法,也标明了常用方法的定义
public interface BeanFactory {/*** Used to dereference a {@link FactoryBean} instance and distinguish it from* beans <i>created</i> by the FactoryBean. For example, if the bean named* {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}* will return the factory, not the instance returned by the factory.*/String FACTORY_BEAN_PREFIX = "&";//key值获取实例,也叫按bean的名称或ID获取对应的实例Object getBean(String name) throws BeansException;//按bean名称以及对应的class获取实例<T> T getBean(String name, Class<T> requiredType) throws BeansException;Object getBean(String name, Object... args) throws BeansException;//按class类型获取bean实例<T> T getBean(Class<T> requiredType) throws BeansException;<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);//判断是否有对应的bean名称boolean containsBean(String name);//判断对应的bean名称是否为单例boolean isSingleton(String name) throws NoSuchBeanDefinitionException;//判断对应的bean名称是否为多例boolean isPrototype(String name) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;//按bean名称获取对应的class@NullableClass<?> getType(String name) throws NoSuchBeanDefinitionException;String[] getAliases(String name);}
不过这里面有个常量FACTORY_BEAN_PREFIX这个跟FactoryBean有关。
FactoryBean
也是注入Bean实现的一种方法,先看一下这个接口:
public interface FactoryBean<T> {//获取对象@NullableT getObject() throws Exception;//获取对象对应的class@NullableClass<?> getObjectType();//是否为单例,默认为是default boolean isSingleton() {return true;}}
用法是实现这个接口,并且注入到Spring的IOC容器当中,示例:
@Component
public class SpringTest03FactoryBean implements FactoryBean<Fish> {public Fish getObject() throws Exception {return new Fish();}public Class<?> getObjectType() {return Fish.class;}public boolean isSingleton() {return true;}}
当时在从容器中取这个对应的bean名称的时候,确实返回getObject()中返回的对象,但是如果需要获取这个FactoryBean的对象的话,需在bean名称前面加个&,才能获取到对应的FactoryBean实现类的实例
这个看起来用的不多但是,在Mybatis和Spring的融合包中能够看到FactoryBean的身影,是专门将动态代理的dao接口注入到Spring的容器当中,这个后面再说
接下来看看在Spring源码中是在哪里处理了这个&符号
在Spring加载FactoryBean的时候,仅仅是将它当作一个普通的Bean注入
而在getBean的时候就会有区分
在AbstractBeanFactory的1658行,如果带有&则直接返回FactoryBean的实例
否则接着往下走
直接获取 factoryBeanObjectCache 对应的key值,没有话会先加载到factoryBeanObjectCache
这两种其实是两个不同的类,只是名字看着看不多而已