官方定义
- BeanFactory:Spring Bean容器的根接口
- FactoryBean:各个对象的工厂接口,如果bean实现了这个接口,它将被用作对象的工厂,而不是直接作为bean实例。
源码解析
BeanFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; Object getBean(String name) throws BeansException; <T> T getBean(String name, Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType, Object... args) throws BeansException; boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException; Class<?> getType(String name) throws NoSuchBeanDefinitionException; String[] getAliases(String name); }
|
从源码的方法定义上,就可以看出,BeanFactory
作为bean的容器管理器,提供了一系列获取bean以及获取bean属性的方法。
写一个小例子试验下:
SimpleBean:
1 2 3 4 5
| public class SimpleBean { public void send() { System.out.println("Hello Spring Bean!"); } }
|
Spring配置文件config.xml:
1 2 3 4 5 6 7 8 9 10
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="simpleBean" class="base.SimpleBeanFactoryBean"/> </beans>
|
测试方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public static void main(String[] args) throws Exception { ApplicationContext context = new ClassPathXmlApplicationContext("config.xml"); BeanFactory beanFactory = context.getAutowireCapableBeanFactory(); System.out.println("通过名称获取bean"); SimpleBean simpleBean = (SimpleBean) beanFactory.getBean("simpleBean"); simpleBean.send(); System.out.println("通过名称和类型获取bean"); simpleBean = beanFactory.getBean("simpleBean", SimpleBean.class); simpleBean.send(); System.out.println("通过类型获取bean"); simpleBean = beanFactory.getBean(SimpleBean.class); simpleBean.send(); boolean containsBean = beanFactory.containsBean("simpleBean"); System.out.println("是否包含 simpleBean ? " + containsBean); boolean singleton = beanFactory.isSingleton("simpleBean"); System.out.println("是否是单例? " + singleton); boolean match = beanFactory.isTypeMatch("simpleBean", ResolvableType.forClass(SimpleBean.class)); System.out.println("是否是SimpleBean类型 ? " + match); match = beanFactory.isTypeMatch("simpleBean", SimpleBean.class); System.out.println("是否是SimpleBean类型 ? " + match); Class<?> aClass = beanFactory.getType("simpleBean"); System.out.println("simpleBean 的类型是 " + aClass.getName()); String[] aliases = beanFactory.getAliases("simpleBean"); System.out.println("simpleBean 的别名 : " + Arrays.toString(aliases)); }
|
控制台结果:
1 2 3 4 5 6 7 8 9 10 11 12
| 通过名称获取bean Hello Spring Bean! 通过名称和类型获取bean Hello Spring Bean! 通过类型获取bean Hello Spring Bean! 是否包含 simpleBean ? true 是否是单例? true 是否是SimpleBean类型 ? true 是否是SimpleBean类型 ? true simpleBean 的类型是 base.SimpleBean simpleBean 的别名 : []
|
FactoryBean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
|
接口是泛型,定义了三个方法,其中getObject()
是工厂模式的体现,将会通过此方法返回一个bean的实例。
一个小例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class SimpleBeanFactoryBean implements FactoryBean<SimpleBean> { @Override public SimpleBean getObject() throws Exception { System.out.println("MyFactoryBean getObject"); return new SimpleBean(); }
@Override public Class<?> getObjectType() { System.out.println("MyFactoryBean getObjectType"); return SimpleBean.class; }
@Override public boolean isSingleton() { return false; } }
|
以上可以修改为单例模式,可以做成线程安全的单例,可塑性较高。
配置文件config.xml:
1 2 3 4 5 6 7 8 9 10
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="simple" class="base.SimpleBeanFactoryBean"/> </beans>
|
注意,我们在这里只配置了SimpleBeanFactoryBean
,并没有配置SimpleBean
,接下来看下getBean
方法的输出。
1 2 3
| ApplicationContext context = new ClassPathXmlApplicationContext("config.xml"); SimpleBean simpleBean = context.getBean(SimpleBean.class); simpleBean.send();
|
控制台输出:
1 2 3
| MyFactoryBean getObjectType MyFactoryBean getObject Hello Spring Bean!
|
由此我们可以看出FactoryBean
的执行流程
- 通过
getObjectType
获取bean的类型
- 调用
getObject
方法获取bean的实例
总结
BeanFactory
和FactoryBean
其实没有关系,只是名称比较像而已。
BeanFactory
是IOC最基本的容器,负责生产和管理bean,它为其他具体的IOC容器提供了最基本的规范。
FactoryBean
是一个接口,当在IOC容器中的Bean实现了FactoryBean
后,通过getBean(String BeanName)
获取到的Bean对象并不是FactoryBean
的实现类对象,而是这个实现类中的getObject()
方法返回的对象。要想获取FactoryBean
的实现类,就要getBean(&BeanName)
,在BeanName
之前加上&。