一、基础容器接口
org.springframework.beans.factory 这里是定义spring IOC容器接口的包,在这个包里有我们熟悉的BeanFactory 。
public interface BeanFactory {
/**
* 用于创建FactoryBean实例。
* 举例说明,如果创建了一个叫做myJndiObject的FactoryBean,getting时就会得到一个factory,而不是factory返回的实例。
*/
String FACTORY_BEAN_PREFIX = "&";
/**
* 返回一个被共享或独立的指定bean。
* <p>这个方法允许Spring BeanFactory被用于替代单例模式或原型模式。
* 主叫方可以保留单例beans返回对象的引用
* <p>别名转义到对应的规范的bean名。
* 询问父工厂是否该bean存在这个工厂实例中
* @param name 被检索的bean名
* @return bean的一个实例
* @throws NoSuchBeanDefinitionException 如果没有指定名称的bean定义
* @throws BeansException 如果得不到bean
*/
Object getBean(String name) throws BeansException;
/**
* 返回一个被共享或独立的指定bean
* <p>文如其名,如果bean不提供需要的类型,
* 则通过抛出BeanNotOfRequiredTypeException来提供一个类型安全的措施。
* 这意味着ClassCastException不能在强转结果时被正确的抛出。
* <p>别名转义到对应的规范的bean名。
* 询问父工厂是否该bean存在这个工厂实例中
* @param name 被检索的bean名
* @param requiredType type bean的类型-
* @return bean的一个实例
* @throws NoSuchBeanDefinitionException 如果没有指定名称的bean定义
* @throws BeanNotOfRequiredTypeException 如果bean的类型不对
* @throws BeansException 如果bean不能被创建
*/
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
/**
* 不高兴写了
* @since 3.0
* @see ListableBeanFactory
*/
<T> T getBean(Class<T> requiredType) throws BeansException;
/**
* @since 2.5
*/
Object getBean(String name, Object... args) throws BeansException;
/**
* 该bean工厂是否定义或注册了某个名字的单例实例
* <p>如果是别名,则会转为相应的规范名称
* <p>如果该工厂是分级的,将会在找不到该工厂实例时询问父工厂
* <p>如果bean定义了或是单例实现了实例了,该方法会返回true。
* @param name 要查询的bean的名称
* @return whether 该bean是否存在
*/
boolean containsBean(String name);
/**
* 该bean是否为一个共享的单例?也就是说,getBean方法是否返回相同名称的实例。
* <p>注释:该方法返回false并不说明就返回的是独立的实例。
* 只是说明非单例实例,也可以对应范围内的bean。
* 使用isPrototype显式检查独立实例。
* <p>Translates aliases back to the corresponding canonical bean name.
* Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @return whether this bean corresponds to a singleton instance
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @see #getBean
* @see #isPrototype
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
* 检查是否为原型模式
* <p>Note: This method returning {@code false} does not clearly indicate
* a singleton object. It indicates non-independent instances, which may correspond
* to a scoped bean as well. Use the {@link #isSingleton} operation to explicitly
* check for a shared singleton instance.
* <p>Translates aliases back to the corresponding canonical bean name.
* Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @return whether this bean will always deliver independent instances
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @since 2.0.3
* @see #getBean
* @see #isSingleton
*/
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
/**
* Check whether the bean with the given name matches the specified type.
* More specifically, check whether a {@link #getBean} call for the given name
* would return an object that is assignable to the specified target type.
* <p>Translates aliases back to the corresponding canonical bean name.
* Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @param targetType the type to match against
* @return {@code true} if the bean type matches,
* {@code false} if it doesn't match or cannot be determined yet
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @since 2.0.1
* @see #getBean
* @see #getType
*/
boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
/**
* Determine the type of the bean with the given name. More specifically,
* determine the type of object that {@link #getBean} would return for the given name.
* <p>For a {@link FactoryBean}, return the type of object that the FactoryBean creates,
* as exposed by {@link FactoryBean#getObjectType()}.
* <p>Translates aliases back to the corresponding canonical bean name.
* Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @return the type of the bean, or {@code null} if not determinable
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @since 1.1.2
* @see #getBean
* @see #isTypeMatch
*/
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
/**
* Return the aliases for the given bean name, if any.
* All of those aliases point to the same bean when used in a {@link #getBean} call.
* <p>If the given name is an alias, the corresponding original bean name
* and other aliases (if any) will be returned, with the original bean name
* being the first element in the array.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the bean name to check for aliases
* @return the aliases, or an empty array if none
* @see #getBean
*/
String[] getAliases(String name);
}
该工厂接口只规定了规范,具体的实现就由其他实现类来实现这些规范了。就相当于把一个房子的毛坯搞定了,具体要怎么装修就由业主自己去实现了,只管卖了怎么搞就随便了。
二、IOC容器
基本就由最熟悉的XmlBeanFactory入手
@Deprecated
@SuppressWarnings({"serial", "all"})
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
/**
* Create a new XmlBeanFactory with the given resource,
* which must be parsable using DOM.
* @param resource XML resource to load bean definitions from
* @throws BeansException in case of loading or parsing errors
*/
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
/**
* Create a new XmlBeanFactory with the given input stream,
* which must be parsable using DOM.
* @param resource XML resource to load bean definitions from
* @param parentBeanFactory parent bean factory
* @throws BeansException in case of loading or parsing errors
*/
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
看了代码才发现XmlBeanFactory都已经被标注过时了……
从构造方法看出XmlBeanFactory主要用于加载资源,具体资源内部结构和资源配置就留到下一节再看了。