spring中的BeanFactory和FactoryBean的区别与联系

理解spring中的BeanFactory和FactoryBean的区别与联系

https://blog.csdn.net/joenqc/article/details/66479154

https://blog.csdn.net/wangbiao007/article/details/53183764

首先,这俩都是个接口…

实现 BeanFactory 接口的类表明此类事一个工厂,作用就是配置、新建、管理 各种Bean。

而 实现 FactoryBean 的类表明此类也是一个Bean,类型为工厂Bean(Spring中共有两种bean,一种为普通bean,另一种则为工厂bean)。顾名思义,它也是用来管理Bean的,而它本身由spring管理。

一个Bean想要实现 FactoryBean ,必须实现以下三个接口:

1. Object getObject():返回由FactoryBean创建的Bean的实例

2. boolean isSingleton():确定由FactoryBean创建的Bean的作用域是singleton还是prototype;

3. getObjectType():返回FactoryBean创建的Bean的类型。

有一点需要注意,如果将一个实现了FactoryBean的类成功配置到了spring上下文中,那么通过该类对象的名称(比如appleFactoryBean)从spring的applicationContext或者beanFactory获取bean时,获取到的是appleFactoryBean创建的apple实例,而不是appleFactoryBean自己,如果想通过spring拿到appleFactoryBean,需要在名称前加 & 符号 :

out.println(applicationContext.getBean("&appleFactoryBean"))
  • 1

这个prefix在BeanFactory接口源码中有提到:

/**
* Used to dereference a {@link FactoryBean} instance and distinguish it from
* beans <i>created</i> by the FactoryBean. For example, if the bean named
* {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
* will return the factory, not the instance returned by the factory.
*/
    String FACTORY_BEAN_PREFIX = "&";

还有一点需要注意,FactoryBean管理的bean实际上也是由spring进行配置、实例化、管理,因此由FactoryBean管理的bean不能再次配置到spring配置文件中(xml、java类配置、注解均不可以),否则会报如下异常:

Exception in thread "main" org.springframework.beans.factory.BeanIsNotAFactoryException: Bean named 'appleFactoryBean' is expected to be of type 'org.springframework.beans.factory.FactoryBean' but was actually of type 'java.lang.Object'
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1612)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:317)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:742)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
    at com.joen.testspringcontainer.Start.main(Start.java:11)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

附上一个例子:

spring配置类:

@Configuration
@ComponentScan
public class Configurations {
}

AppleBean :

//@Component  这里不可以加注解 !!!!!!
public class AppleBean{

}

AppleFactoryBean :

@Component
public class AppleFactoryBean implements FactoryBean{

    public Object getObject() throws Exception {
        return new AppleBean();
    }

    public Class<?> getObjectType() {
        return AppleBean.class;
    }

    public boolean isSingleton() {
        return false;
    }
}

启动类 :

public class Start {
    public static void main(String[] args){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Configurations.class);
                 out.println(applicationContext.getBean("appleFactoryBean"));//得到的是apple
                 out.println(applicationContext.getBean("&appleFactoryBean"));//得到的是apple工厂
    }
}

 

 

 

1.BeanFactory

             BeanFactory是IOC最基本的容器,负责生产和管理bean,它为其他具体的IOC容器提供了最基本的规范,例如DefaultListableBeanFactory,

XmlBeanFactory,ApplicationContext 等具体的容器都是实现了BeanFactory,再在其基础之上附加了其他的功能。

 BeanFactory源码             

 
  1. package org.springframework.beans.factory;

  2. import org.springframework.beans.BeansException;

  3. public interface BeanFactory {

  4. String FACTORY_BEAN_PREFIX = "&";

  5. Object getBean(String name) throws BeansException;

  6. <T> T getBean(String name, Class<T> requiredType) throws BeansException;

  7. <T> T getBean(Class<T> requiredType) throws BeansException;

  8. Object getBean(String name, Object... args) throws BeansException;

  9. boolean containsBean(String name);

  10. boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

  11. boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

  12. boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;

  13. Class<?> getType(String name) throws NoSuchBeanDefinitionException;

  14. String[] getAliases(String name);

  15. }

        2.FactoryBean

 

             FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。要想获取FactoryBean的实现类,就要getBean(&BeanName),在BeanName之前加上&。

 FactoryBean源码

 

 
  1. package org.springframework.beans.factory;

  2. public interface FactoryBean<T> {

  3. T getObject() throws Exception;

  4. Class<?> getObjectType();

  5. boolean isSingleton();

  6. }

下面是一个应用FactoryBean的例子

 

 
  1. <beans xmlns="http://www.springframework.org/schema/beans"

  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  3. xmlns:context="http://www.springframework.org/schema/context"

  4. xmlns:aop="http://www.springframework.org/schema/aop"

  5. xmlns:tx="http://www.springframework.org/schema/tx"

  6. xsi:schemaLocation="http://www.springframework.org/schema/beans

  7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

  8. http://www.springframework.org/schema/context

  9. http://www.springframework.org/schema/context/spring-context-3.0.xsd

  10. http://www.springframework.org/schema/aop

  11. http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

  12. http://www.springframework.org/schema/tx

  13. http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

  14.  
  15. <bean id="student" class="com.spring.bean.Student">

  16. <property name="name" value="zhangsan" />

  17. </bean>

  18.  
  19. <bean id="school" class="com.spring.bean.School">

  20. </bean>

  21.  
  22. <bean id="factoryBeanPojo" class="com.spring.bean.FactoryBeanPojo">

  23. <property name="type" value="student" />

  24. </bean>

  25. </beans>


FactoryBean的实现类

 

 
  1. import org.springframework.beans.factory.FactoryBean;

  2.  
  3. /**

  4. * @author 作者 wangbiao

  5. * @date 创建时间:2016年11月14日 上午11:19:31

  6. * @parameter

  7. * @return

  8. */

  9. public class FactoryBeanPojo implements FactoryBean{

  10. private String type;

  11.  
  12. @Override

  13. public Object getObject() throws Exception {

  14. if("student".equals(type)){

  15. return new Student();

  16. }else{

  17. return new School();

  18. }

  19.  
  20. }

  21.  
  22. @Override

  23. public Class getObjectType() {

  24. return School.class;

  25. }

  26.  
  27. @Override

  28. public boolean isSingleton() {

  29. return true;

  30. }

  31.  
  32. public String getType() {

  33. return type;

  34. }

  35.  
  36. public void setType(String type) {

  37. this.type = type;

  38. }

  39.  
  40. }


普通的bean

 

 
  1. /**

  2. * @author 作者 wangbiao

  3. * @date 创建时间:2016年11月14日 上午11:13:18

  4. * @parameter

  5. * @return

  6. */

  7. public class School {

  8. private String schoolName;

  9. private String address;

  10. private int studentNumber;

  11. public String getSchoolName() {

  12. return schoolName;

  13. }

  14. public void setSchoolName(String schoolName) {

  15. this.schoolName = schoolName;

  16. }

  17. public String getAddress() {

  18. return address;

  19. }

  20. public void setAddress(String address) {

  21. this.address = address;

  22. }

  23. public int getStudentNumber() {

  24. return studentNumber;

  25. }

  26. public void setStudentNumber(int studentNumber) {

  27. this.studentNumber = studentNumber;

  28. }

  29. @Override

  30. public String toString() {

  31. return "School [schoolName=" + schoolName + ", address=" + address

  32. + ", studentNumber=" + studentNumber + "]";

  33. }

  34. }

测试类

 

 
  1. import org.springframework.context.support.ClassPathXmlApplicationContext;

  2.  
  3. import com.spring.bean.FactoryBeanPojo;

  4.  
  5. /**

  6. * @author 作者 wangbiao

  7. * @date 创建时间:2016年11月14日 上午11:11:35

  8. * @parameter

  9. * @return

  10. */

  11. public class FactoryBeanTest {

  12. public static void main(String[] args){

  13. String url = "com/spring/config/BeanConfig.xml";

  14. ClassPathXmlApplicationContext cpxa = new ClassPathXmlApplicationContext(url);

  15. Object school= cpxa.getBean("factoryBeanPojo");

  16. FactoryBeanPojo factoryBeanPojo= (FactoryBeanPojo) cpxa.getBean("&factoryBeanPojo");

  17. System.out.println(school.getClass().getName());

  18. System.out.println(factoryBeanPojo.getClass().getName());

  19. }

  20. }

输出的结果:

 

 
  1. 十一月 16, 2016 10:28:24 上午 org.springframework.context.support.AbstractApplicationContext prepareRefresh

  2. INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1e8ee5c0: startup date [Wed Nov 16 10:28:24 CST 2016]; root of context hierarchy

  3. 十一月 16, 2016 10:28:24 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions

  4. INFO: Loading XML bean definitions from class path resource [com/spring/config/BeanConfig.xml]

  5. 十一月 16, 2016 10:28:24 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons

  6. INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@35b793ee: defining beans [student,school,factoryBeanPojo]; root of factory hierarchy

  7. com.spring.bean.Student

  8. com.spring.bean.FactoryBeanPojo


从结果上可以看到当从IOC容器中获取FactoryBeanPojo对象的时候,用getBean(String BeanName)获取的确是Student对象,可以看到在FactoryBeanPojo中的type属性设置为student的时候,会在getObject()方法中返回Student对象。所以说从IOC容器获取实现了FactoryBean的实现类时,返回的却是实现类中的getObject方法返回的对象,要想获取FactoryBean的实现类,得在getBean(String BeanName)中的BeanName之前加上&,写成getBean(String &BeanName)。

        3.BeanFactory和FactoryBean的区别

              BeanFactory和FactoryBean其实没有什么比较性的,只是两者的名称特别接近,所以有时候会拿出来比较一番,BeanFactory是提供了OC容器最基本的形式,给具体的IOC容器的实现提供了规范,FactoryBean可以说为IOC容器中Bean的实现提供了更加灵活的方式,FactoryBean在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式,我们可以在getObject()方法中灵活配置。其实在Spring源码中有很多FactoryBean的实现类,要想深入准确的理解FactoryBean,只有去读读Spring源码了。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值