三、通过 FactoryBean 来配置bean
一般情况下,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> 的形式:
- public interface FactoryBean<T> {
- /**
- * Return an instance (possibly shared or independent) of the object
- * managed by this factory.
- * <p>As with a {@link BeanFactory}, this allows support for both the
- * Singleton and Prototype design pattern.
- * <p>If this FactoryBean is not fully initialized yet at the time of
- * the call (for example because it is involved in a circular reference),
- * throw a corresponding {@link FactoryBeanNotInitializedException}.
- * <p>As of Spring 2.0, FactoryBeans are allowed to return {@code null}
- * objects. The factory will consider this as normal value to be used; it
- * will not throw a FactoryBeanNotInitializedException in this case anymore.
- * FactoryBean implementations are encouraged to throw
- * FactoryBeanNotInitializedException themselves now, as appropriate.
- * @return an instance of the bean (can be {@code null})
- * @throws Exception in case of creation errors
- * @see FactoryBeanNotInitializedException
- */
- T getObject() throws Exception;
- /**
- * Return the type of object that this FactoryBean creates,
- * or {@code null} if not known in advance.
- * <p>This allows one to check for specific types of beans without
- * instantiating objects, for example on autowiring.
- * <p>In the case of implementations that are creating a singleton object,
- * this method should try to avoid singleton creation as far as possible;
- * it should rather estimate the type in advance.
- * For prototypes, returning a meaningful type here is advisable too.
- * <p>This method can be called <i>before</i> this FactoryBean has
- * been fully initialized. It must not rely on state created during
- * initialization; of course, it can still use such state if available.
- * <p><b>NOTE:</b> Autowiring will simply ignore FactoryBeans that return
- * {@code null} here. Therefore it is highly recommended to implement
- * this method properly, using the current state of the FactoryBean.
- * @return the type of object that this FactoryBean creates,
- * or {@code null} if not known at the time of the call
- * @see ListableBeanFactory#getBeansOfType
- */
- Class<?> getObjectType();
- /**
- * Is the object managed by this factory a singleton? That is,
- * will {@link #getObject()} always return the same object
- * (a reference that can be cached)?
- * <p><b>NOTE:</b> If a FactoryBean indicates to hold a singleton object,
- * the object returned from {@code getObject()} might get cached
- * by the owning BeanFactory. Hence, do not return {@code true}
- * unless the FactoryBean always exposes the same reference.
- * <p>The singleton status of the FactoryBean itself will generally
- * be provided by the owning BeanFactory; usually, it has to be
- * defined as singleton there.
- * <p><b>NOTE:</b> This method returning {@code false} does not
- * necessarily indicate that returned objects are independent instances.
- * An implementation of the extended {@link SmartFactoryBean} interface
- * may explicitly indicate independent instances through its
- * {@link SmartFactoryBean#isPrototype()} method. Plain {@link FactoryBean}
- * implementations which do not implement this extended interface are
- * simply assumed to always return independent instances if the
- * {@code isSingleton()} implementation returns {@code false}.
- * @return whether the exposed object is a singleton
- * @see #getObject()
- * @see SmartFactoryBean#isPrototype()
- */
- boolean isSingleton();
- }
在该接口中还定义了以下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() 方法。
测试:
- package com.xiya.spring.beans.factorybean;
- /**
- * Created by N3verL4nd on 2017/3/20.
- */
- public class Car {
- private String brand;
- private int price;
- public Car() {
- }
- public Car(String brand, int price) {
- this.brand = brand;
- this.price = price;
- }
- public String getBrand() {
- return brand;
- }
- public void setBrand(String brand) {
- this.brand = brand;
- }
- public int getPrice() {
- return price;
- }
- public void setPrice(int price) {
- this.price = price;
- }
- @Override
- public String toString() {
- return "Car{" +
- "brand='" + brand + '\'' +
- ", price=" + price +
- '}';
- }
- }
- package com.xiya.spring.beans.factorybean;
- import org.springframework.beans.factory.FactoryBean;
- /**
- * 通过 FactoryBean 来配置bean
- * 需要实现 FactoryBean 接口
- * Created by N3verL4nd on 2017/3/20.
- */
- public class CarFactoryBean implements FactoryBean<Car> {
- private String brand;
- public void setBrand(String brand) {
- this.brand = brand;
- }
- public void fun() {
- System.out.println("CarFactoryBean::fun()");
- }
- //返回bean的对象
- @Override
- public Car getObject() throws Exception {
- Car car = new Car(brand, 500000);
- return car;
- }
- //返回bean的类型
- @Override
- public Class<?> getObjectType() {
- return Car.class;
- }
- //返回bean是不是单实例
- @Override
- public boolean isSingleton() {
- return true;
- }
- }
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <!--
- 通过 FactoryBean 来配置 bean 的实例
- class: 指向 FactoryBean 的全类名
- property: 配置 FactoryBean 的属性
- 但实际返回的实例却是 FactoryBean 的 getObject()方法返回的实例。
- -->
- <bean id="car" class="com.xiya.spring.beans.factorybean.CarFactoryBean">
- <property name="brand" value="BMW"/>
- </bean>
- </beans>
输出:
Car{brand='BMW', price=500000}
CarFactoryBean::fun()
Process finished with exit code 0
总之,当需要依赖现有的bean时,可以利用FactoryBean
三、通过 FactoryBean 来配置bean的更多相关文章
- Spring学习记录(十)---使用FactoryBean配置Bean
之前学了,配置bean可以用普通全类名配置.用工厂方法配置,FactoryBean又是什么呢 有时候配置bean要用到,IOC其他Bean,这时,用FactoryBean配置最合适. FactoryB ...
- 通过FactoryBean配置Bean
这是配置Bean的第三种方式,FactoryBean是Spring为我们提供的,我们先来看看源码: 第一个方法:public abstract T getObject() throws Excepti ...
- 4.spriing:Bean的生命周期/工厂方法配置Bean/FactoryBean
1.Bean的生命周期 scope:singleton/prototype 1)spring容器管理singleton作用的生命周期,spring能够精确知道Bean合适创建,何时初始化完成,以及何时 ...
- Spring4.0学习笔记(7) —— 通过FactoryBean配置Bean
1.实现Spring 提供的FactoryBean接口 package com.spring.facoryBean; import org.springframework.beans.factory. ...
- spring FactoryBean配置Bean
概要: 实例代码具体解释: 文件夹结构 Car.java package com.coslay.beans.factorybean; public class Car { private String ...
- Spring配置bean的方法(工厂方法和Factorybean)
通过工厂方法配置bean 通过调用静态工厂方法创建bean 通过静态工厂方法创建bean是将对象创建的过程封装到静态方法中.当客户端需要对象时,只需要简单地调用静态方法,而不关心创建对象的细节. 要声 ...
- spring4-2-bean配置-10-通过FactoryBean配置bean
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAk8AAAFHCAIAAAA3Hj/JAAAgAElEQVR4nO2dzdX0rA2Gp6asclwQTW
- Spring_通过 FactoryBean 配置 Bean
beans-factorybean.xml <?xml version="1.0" encoding="UTF-8"?><beans xmln ...
- 12.Spring通过FactoryBean配置Bean
为啥要使用FactoryBean: 在配置Bean的时候,需要用到IOC容器中的其它Bean,这个时候使用FactoryBean配置最合适. public class Car { private St ...
随机推荐
- selenium自动化测试入门 定位frame和iframe中的元素对象
< frame> <iframe> 标签,浏览器会在标签中打开一个特定的页面窗口(框架),它在本窗口中嵌套进入一个网页,当用selenium定位页面元素的时候会遇到定位不到fr ...
- .Net Core Web Api实践(二).net core+Redis+IIS+nginx实现Session共享
前言:虽说公司app后端使用的是.net core+Redis+docker+k8s部署的,但是微信公众号后端使用的是IIS部署的,虽说公众号并发量不大,但领导还是使用了负载均衡,所以在介绍docke ...
- [转载] Windows系统批处理延迟方法
小贴士:方法四 亲测有效,因为当时对于精确度要求不是很高,所以没有具体测试它的精确度.其他方法没有测过,用到的时候再测吧! 批处理延时启动的几个方法 方法一:ping 缺点:时间精度为1秒,不够精确 ...
- vue报错 [Intervention] Ignored attempt to cancel a touchmove event with cancelable
在vue开发中使用vue-awesome-swiper制作轮播图,手动拖动时会报错,解决方案: 需要滑动的标签 { touch-action: none; } -------------------- ...
- pymysql总结
一.创建数据库 import pymysql conn = pymysql.connect(host='ip', user='root', password='密码') # 以字典的形式返回操作结果 ...
- redis 注意事项
1.scan_iter car_key = 'shopping*' # print(car_key) data_li = [] for i in con.scan_iter(car_key): # p ...
- Qt Installer Framework翻译(3-4)
更新组件 下图说明了用于更新已安装组件的默认工作流程: 本节使用在macOS上运行的Qt 5维护工具为例,来演示用户如何更新已安装组件. 启动更新程序 用户启动维护工具时,将打开"简介&qu ...
- SSAS Tabular表格模型实现动态权限管理
最近忽然对SSAS产生了浓厚兴趣,我看博客园上也米有写关于SSAS 2016下表格模型实现动态权限管理的文章,最近鼓捣了一下微软的样例,鼓捣好了,把过程中遇到的一些问题写出来,抛砖引玉,也算给自己一个 ...
- 【java面试】集合类篇
java中主要的类集合接口如下 Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├Has ...
- 大叔 Frameworks.Entity.Core 2 PageList
Frameworks.Entity.Core\Commons\PageList\ 1 分页通用类 ListPageList<T> 继承 PageListBase<T>, IP ...