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 6T getBean(String var1, Class var2) throws BeansException; 7 8 T getBean(Class var1) throws BeansException; 9 10 Object getBean(String var1, Object... var2) throws BeansException; 11 12 T getBean(Class 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通过反射机制利用
如果按照传统的方式,则需要在
Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。
说白了就是个普通的Bean,而这个bean可以自定义实现实例化,不想写xml配置,以及里面注入的内容很负责,写配置很困难等情况,跟注解版的@Bean 很相似,用的装饰设计模式,可新增功能。
源代码如下:
1 public interface FactoryBean{ 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 FactoryBean2 { 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 }
class="qt.Dto.MyBean">
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:张三
用&来识别