官方定义
- BeanFactory:Spring Bean容器的根接口
- FactoryBean:各个对象的工厂接口,如果bean实现了这个接口,它将被用作对象的工厂,而不是直接作为bean实例。
源码解析
BeanFactory
public interface BeanFactory { //标注是获取FactoryBean的实现类,而不是调用getObject()获取的实例 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:
public class SimpleBean { public void send() { System.out.println("Hello Spring Bean!"); } }
Spring配置文件config.xml:
<?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>
测试方法:
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)); }
控制台结果:
通过名称获取bean Hello Spring Bean! 通过名称和类型获取bean Hello Spring Bean! 通过类型获取bean Hello Spring Bean! 是否包含 simpleBean ? true 是否是单例? true 是否是SimpleBean类型 ? true 是否是SimpleBean类型 ? true simpleBean 的类型是 base.SimpleBean simpleBean 的别名 : []
FactoryBean
public interface FactoryBean<T> { /** * 获取一个bean,如果配置了工厂bean,在getBean的时候,将会调用此方法,获取一个bean */ T getObject() throws Exception; /** * 获取bean的类型 */ Class<?> getObjectType(); /** * 是否是单例 */ boolean isSingleton(); }
接口是泛型,定义了三个方法,其中getObject()
是工厂模式的体现,将会通过此方法返回一个bean的实例。
一个小例子:
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:
<?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
方法的输出。
ApplicationContext context = new ClassPathXmlApplicationContext("config.xml"); SimpleBean simpleBean = context.getBean(SimpleBean.class); simpleBean.send();
控制台输出:
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
之前加上&。
来源:https://www.cnblogs.com/gcdd/p/12292360.html