先介紹一下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?
這兩種其實是兩個不同的類,只是名字看著看不多而已