Spring之BeanFactory和FactoryBean接口的区别

Spring之BeanFactory和FactoryBean接口的区别

BeanFactory和FactoryBean 2个很相似,但是区别很大。

1、BeanFactory 

BeanFactory接口是Spring容器的核心接口,负责:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

ApplicationContext 这个应用上下文,我们经常用到,如

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

而它就是继承了BeanFactory ,才会有可以getBean(String name) 这个功能。

源代码如下:

 1 public interface BeanFactory {
 2     String FACTORY_BEAN_PREFIX = "&";
 3 
 4     Object getBean(String var1) throws BeansException;
 5 
 6     <T> T getBean(String var1, Class<T> var2) throws BeansException;
 7 
 8     <T> T getBean(Class<T> var1) throws BeansException;
 9 
10     Object getBean(String var1, Object... var2) throws BeansException;
11 
12     <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
13 
14     boolean containsBean(String var1);
15 
16     boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
17 
18     boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
19 
20     boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
21 
22     boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
23 
24     Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
25 
26     String[] getAliases(String var1);
27 }

2、FactoryBean

一般情况下,Spring通过反射机制利用<bean>的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,

如果按照传统的方式,则需要在<bean>中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。

Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。

说白了就是个普通的Bean,而这个bean可以自定义实现实例化,不想写xml配置,以及里面注入的内容很负责,写配置很困难等情况,跟注解版的@Bean 很相似,用的装饰设计模式,可新增功能。

源代码如下:

1 public interface FactoryBean<T> {
2     T getObject() throws Exception;
3 
4     Class<?> getObjectType();
5 
6     boolean isSingleton();
7 }

很明显调用getObect方法就相当于applicationContext.getBean("student")

具体使用如下:

自定义创建了Mybean.class,实现FactoryBean接口

 1 public class MyBean implements FactoryBean<Student>
 2 {
 3     @Override
 4     public Student getObject() throws Exception
 5     {
 6         return new Student(){{
 7             setName("张三");
 8         }};
 9     }
10 
11     @Override
12     public Class<?> getObjectType()
13     {
14         return Student.class;
15     }
16 
17     @Override
18     public boolean isSingleton()
19     {
20         return true;
21     }
22 }
<bean ></bean>
1 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
2 Object myBean = applicationContext.getBean("myBean");
3 System.out.println("isStudentBean:" + isStudentBean);
4 System.out.println("myBean name:" + ((Student) myBean).getName());

输出:

isStudentBean:true
myBean name:张三

从上面的执行来看,明明注册className的是qt.Dto.MyBean, 最后获取的竟然是Student对象,不是本身的MyBean对象,

很明显它调用的就是getObject方法,核心就是个代理方式

如果我就想获取MyBean对象呢,还是有办法的,在对象 id前加 &就可以

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Object myBean1 = applicationContext.getBean("&myBean");
boolean isMyBean = myBean instanceof MyBean;
System.out.println("isMyBean:" + isMyBean);
System.out.println("myBean name:" + myBean1);

输出:

isStudentBean:true
myBean name:张三

用&来识别