一般情况下,Spring 通过反射机制利用 <bean> 的 class 属性指定实现类实例化 Bean ,在某些情况下,实例化 Bean 过程比较复杂,如果按照传统的方式,则需要在 <bean> 中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。 Spring 为此提供了一个 org.springframework.bean.factory.FactoryBean 的工厂类接口,用户可以通过实现该接口定制实例化 Bean 的逻辑。

FactoryBean接口对于 Spring 框架来说占用重要的地位, Spring 自身就提供了 70 多个 FactoryBean 的实现。它们隐藏了实例化一些复杂 Bean 的细节,给上层应用带来了便利。从 Spring 3.0 开始, FactoryBean 开始支持泛型,即接口声明改为 FactoryBean<T> 的形式:

  1. public interface FactoryBean<T> {
  2.  
  3. /**
  4. * Return an instance (possibly shared or independent) of the object
  5. * managed by this factory.
  6. * <p>As with a {@link BeanFactory}, this allows support for both the
  7. * Singleton and Prototype design pattern.
  8. * <p>If this FactoryBean is not fully initialized yet at the time of
  9. * the call (for example because it is involved in a circular reference),
  10. * throw a corresponding {@link FactoryBeanNotInitializedException}.
  11. * <p>As of Spring 2.0, FactoryBeans are allowed to return {@code null}
  12. * objects. The factory will consider this as normal value to be used; it
  13. * will not throw a FactoryBeanNotInitializedException in this case anymore.
  14. * FactoryBean implementations are encouraged to throw
  15. * FactoryBeanNotInitializedException themselves now, as appropriate.
  16. * @return an instance of the bean (can be {@code null})
  17. * @throws Exception in case of creation errors
  18. * @see FactoryBeanNotInitializedException
  19. */
  20. T getObject() throws Exception;
  21.  
  22. /**
  23. * Return the type of object that this FactoryBean creates,
  24. * or {@code null} if not known in advance.
  25. * <p>This allows one to check for specific types of beans without
  26. * instantiating objects, for example on autowiring.
  27. * <p>In the case of implementations that are creating a singleton object,
  28. * this method should try to avoid singleton creation as far as possible;
  29. * it should rather estimate the type in advance.
  30. * For prototypes, returning a meaningful type here is advisable too.
  31. * <p>This method can be called <i>before</i> this FactoryBean has
  32. * been fully initialized. It must not rely on state created during
  33. * initialization; of course, it can still use such state if available.
  34. * <p><b>NOTE:</b> Autowiring will simply ignore FactoryBeans that return
  35. * {@code null} here. Therefore it is highly recommended to implement
  36. * this method properly, using the current state of the FactoryBean.
  37. * @return the type of object that this FactoryBean creates,
  38. * or {@code null} if not known at the time of the call
  39. * @see ListableBeanFactory#getBeansOfType
  40. */
  41. Class<?> getObjectType();
  42.  
  43. /**
  44. * Is the object managed by this factory a singleton? That is,
  45. * will {@link #getObject()} always return the same object
  46. * (a reference that can be cached)?
  47. * <p><b>NOTE:</b> If a FactoryBean indicates to hold a singleton object,
  48. * the object returned from {@code getObject()} might get cached
  49. * by the owning BeanFactory. Hence, do not return {@code true}
  50. * unless the FactoryBean always exposes the same reference.
  51. * <p>The singleton status of the FactoryBean itself will generally
  52. * be provided by the owning BeanFactory; usually, it has to be
  53. * defined as singleton there.
  54. * <p><b>NOTE:</b> This method returning {@code false} does not
  55. * necessarily indicate that returned objects are independent instances.
  56. * An implementation of the extended {@link SmartFactoryBean} interface
  57. * may explicitly indicate independent instances through its
  58. * {@link SmartFactoryBean#isPrototype()} method. Plain {@link FactoryBean}
  59. * implementations which do not implement this extended interface are
  60. * simply assumed to always return independent instances if the
  61. * {@code isSingleton()} implementation returns {@code false}.
  62. * @return whether the exposed object is a singleton
  63. * @see #getObject()
  64. * @see SmartFactoryBean#isPrototype()
  65. */
  66. boolean isSingleton();
  67.  
  68. }

在该接口中还定义了以下3 个方法:

  • T getObject():返回由 FactoryBean 创建的 Bean 实例,如果 isSingleton() 返回 true ,则该实例会放到 Spring 容器中单实例缓存池中;
  • boolean isSingleton():返回由 FactoryBean 创建的 Bean 实例的作用域是 singleton 还是 prototype ;
  • Class<T> getObjectType():返回 FactoryBean 创建的 Bean 类型。

当配置文件中<bean> 的 class 属性配置的实现类是 FactoryBean 时,通过 getBean() 方法返回的不是 FactoryBean 本身,而是 FactoryBean#getObject() 方法所返回的对象,相当于 FactoryBean#getObject() 代理了 getBean() 方法。

测试:

  1. package com.xiya.spring.beans.factorybean;
  2.  
  3. /**
  4. * Created by N3verL4nd on 2017/3/20.
  5. */
  6. public class Car {
  7. private String brand;
  8. private int price;
  9.  
  10. public Car() {
  11. }
  12.  
  13. public Car(String brand, int price) {
  14. this.brand = brand;
  15. this.price = price;
  16. }
  17.  
  18. public String getBrand() {
  19. return brand;
  20. }
  21.  
  22. public void setBrand(String brand) {
  23. this.brand = brand;
  24. }
  25.  
  26. public int getPrice() {
  27. return price;
  28. }
  29.  
  30. public void setPrice(int price) {
  31. this.price = price;
  32. }
  33.  
  34. @Override
  35. public String toString() {
  36. return "Car{" +
  37. "brand='" + brand + '\'' +
  38. ", price=" + price +
  39. '}';
  40. }
  41. }
  1. package com.xiya.spring.beans.factorybean;
  2.  
  3. import org.springframework.beans.factory.FactoryBean;
  4.  
  5. /**
  6. * 通过 FactoryBean 来配置bean
  7. * 需要实现 FactoryBean 接口
  8. * Created by N3verL4nd on 2017/3/20.
  9. */
  10. public class CarFactoryBean implements FactoryBean<Car> {
  11.  
  12. private String brand;
  13.  
  14. public void setBrand(String brand) {
  15. this.brand = brand;
  16. }
  17.  
  18. public void fun() {
  19. System.out.println("CarFactoryBean::fun()");
  20. }
  21.  
  22. //返回bean的对象
  23. @Override
  24. public Car getObject() throws Exception {
  25. Car car = new Car(brand, 500000);
  26. return car;
  27. }
  28.  
  29. //返回bean的类型
  30. @Override
  31. public Class<?> getObjectType() {
  32. return Car.class;
  33. }
  34.  
  35. //返回bean是不是单实例
  36. @Override
  37. public boolean isSingleton() {
  38. return true;
  39. }
  40. }
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <!--
  6. 通过 FactoryBean 来配置 bean 的实例
  7. class: 指向 FactoryBean 的全类名
  8. property: 配置 FactoryBean 的属性
  9. 但实际返回的实例却是 FactoryBean 的 getObject()方法返回的实例。
  10. -->
  11. <bean id="car" class="com.xiya.spring.beans.factorybean.CarFactoryBean">
  12. <property name="brand" value="BMW"/>
  13. </bean>
  14. </beans>

输出:

Car{brand='BMW', price=500000}

CarFactoryBean::fun()





Process finished with exit code 0

总之,当需要依赖现有的bean时,可以利用FactoryBean

三、通过 FactoryBean 来配置bean的更多相关文章

  1. Spring学习记录(十)---使用FactoryBean配置Bean

    之前学了,配置bean可以用普通全类名配置.用工厂方法配置,FactoryBean又是什么呢 有时候配置bean要用到,IOC其他Bean,这时,用FactoryBean配置最合适. FactoryB ...

  2. 通过FactoryBean配置Bean

    这是配置Bean的第三种方式,FactoryBean是Spring为我们提供的,我们先来看看源码: 第一个方法:public abstract T getObject() throws Excepti ...

  3. 4.spriing:Bean的生命周期/工厂方法配置Bean/FactoryBean

    1.Bean的生命周期 scope:singleton/prototype 1)spring容器管理singleton作用的生命周期,spring能够精确知道Bean合适创建,何时初始化完成,以及何时 ...

  4. Spring4.0学习笔记(7) —— 通过FactoryBean配置Bean

    1.实现Spring 提供的FactoryBean接口 package com.spring.facoryBean; import org.springframework.beans.factory. ...

  5. spring FactoryBean配置Bean

    概要: 实例代码具体解释: 文件夹结构 Car.java package com.coslay.beans.factorybean; public class Car { private String ...

  6. Spring配置bean的方法(工厂方法和Factorybean)

    通过工厂方法配置bean 通过调用静态工厂方法创建bean 通过静态工厂方法创建bean是将对象创建的过程封装到静态方法中.当客户端需要对象时,只需要简单地调用静态方法,而不关心创建对象的细节. 要声 ...

  7. spring4-2-bean配置-10-通过FactoryBean配置bean

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAk8AAAFHCAIAAAA3Hj/JAAAgAElEQVR4nO2dzdX0rA2Gp6asclwQTW

  8. Spring_通过 FactoryBean 配置 Bean

    beans-factorybean.xml <?xml version="1.0" encoding="UTF-8"?><beans xmln ...

  9. 12.Spring通过FactoryBean配置Bean

    为啥要使用FactoryBean: 在配置Bean的时候,需要用到IOC容器中的其它Bean,这个时候使用FactoryBean配置最合适. public class Car { private St ...

随机推荐

  1. selenium自动化测试入门 定位frame和iframe中的元素对象

    < frame> <iframe> 标签,浏览器会在标签中打开一个特定的页面窗口(框架),它在本窗口中嵌套进入一个网页,当用selenium定位页面元素的时候会遇到定位不到fr ...

  2. .Net Core Web Api实践(二).net core+Redis+IIS+nginx实现Session共享

    前言:虽说公司app后端使用的是.net core+Redis+docker+k8s部署的,但是微信公众号后端使用的是IIS部署的,虽说公众号并发量不大,但领导还是使用了负载均衡,所以在介绍docke ...

  3. [转载] Windows系统批处理延迟方法

    小贴士:方法四 亲测有效,因为当时对于精确度要求不是很高,所以没有具体测试它的精确度.其他方法没有测过,用到的时候再测吧! 批处理延时启动的几个方法 方法一:ping 缺点:时间精度为1秒,不够精确 ...

  4. vue报错 [Intervention] Ignored attempt to cancel a touchmove event with cancelable

    在vue开发中使用vue-awesome-swiper制作轮播图,手动拖动时会报错,解决方案: 需要滑动的标签 { touch-action: none; } -------------------- ...

  5. pymysql总结

    一.创建数据库 import pymysql conn = pymysql.connect(host='ip', user='root', password='密码') # 以字典的形式返回操作结果 ...

  6. redis 注意事项

    1.scan_iter car_key = 'shopping*' # print(car_key) data_li = [] for i in con.scan_iter(car_key): # p ...

  7. Qt Installer Framework翻译(3-4)

    更新组件 下图说明了用于更新已安装组件的默认工作流程: 本节使用在macOS上运行的Qt 5维护工具为例,来演示用户如何更新已安装组件. 启动更新程序 用户启动维护工具时,将打开"简介&qu ...

  8. SSAS Tabular表格模型实现动态权限管理

    最近忽然对SSAS产生了浓厚兴趣,我看博客园上也米有写关于SSAS 2016下表格模型实现动态权限管理的文章,最近鼓捣了一下微软的样例,鼓捣好了,把过程中遇到的一些问题写出来,抛砖引玉,也算给自己一个 ...

  9. 【java面试】集合类篇

    java中主要的类集合接口如下 Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├Has ...

  10. 大叔 Frameworks.Entity.Core 2 PageList

    Frameworks.Entity.Core\Commons\PageList\ 1 分页通用类 ListPageList<T> 继承  PageListBase<T>, IP ...