三、通过 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 ...
随机推荐
- $Noip2013/Luogu1967$ 货车运输 最大生成树+倍增$lca$
$Luogu$ $Sol$ 首先当然是构建一棵最大生成树,然后对于一辆货车的起点和终点倍增跑$lca$更新答案就好.记得预处理倍增的时候不仅要处理走了$2^i$步后是那个点,还有这中间经过的路径权值的 ...
- win10纯净版安装及其常用软件集锦(2020新年湘岳阳万江波整理)
win10纯净版安装及其常用软件集锦 1.安装win10纯净版:链接:https://pan.baidu.com/s/1L9yl-LNxxDQbEN_TGswzcA 提取码:u0pt 2.安装WPS2 ...
- ELK日志分析系统搭建
之前一段时间由于版本迭代任务紧,组内代码质量不尽如人意.接二连三的被测试提醒后台错误之后, 我们决定搭建一个后台日志分析系统, 经过几个方案比较后,选择的相对更简单的ELK方案. ELK 是Elast ...
- 1063 计算谱半径 (20 分)C语言
在数学中,矩阵的"谱半径"是指其特征值的模集合的上确界.换言之,对于给定的 n 个复数空间的特征值 { a1+b1 i,⋯,an +bn i },它们的模为实部与 ...
- ruby 编写控制台进度条
ruby 中,$stdout.flush 让控制台当前行内容可以重写,以此我们可以做出进度条的效果. def set_progress(index, char = '*') print (char * ...
- 程序员必知的技术官网系列--mysql篇
mysql 官网 https://www.mysql.com/ 官网布局很简单, 其中常用的两块就是下载和文档这两块, 其中下载没什么可讲的, 本次重点依旧是文档. 首页 mysql 文档导航页 ht ...
- Netty 的基本简单实例【服务端-客户端通信】
Netty是建立在NIO基础之上,Netty在NIO之上又提供了更高层次的抽象. 在Netty里面,Accept连接可以使用单独的线程池去处理,读写操作又是另外的线程池来处理. Accept连接和读写 ...
- spring boot学习笔记(2)
Spring boot集成mybatis的三种方式 一.XML文件 在pom文件里面引入mybatis和数据库的依赖 在application.properties中加入数据源配置 其他和ssm配置完 ...
- 【Java基础总结】IO流
字节流 1. InputStream 字节输入流 代码演示 InputStream in = System.in; System.out.println("int read(byte b) ...
- 8款极具表现力的jQuery/CSS3网页菜单
上一篇我向大家分享了7款效果震憾的HTML5应用组件,今天主要来分享一下CSS3网页菜单,因为在一个网站中,菜单起着举足轻重的作用,所以作为WEB开发人员,我们有必要将网站的菜单设计得尽量完美,下面向 ...