转:Spring FactoryBean源码浅析
http://blog.csdn.net/java2000_wl/article/details/7410714
在Spring BeanFactory容器中管理两种bean
1.标准Java Bean
2,另一种是工厂Bean, 即实现了FactoryBean接口的bean 它不是一个简单的Bean 而是一个生产或修饰对象生成的工厂Bean
在向Spring容器获得bean时 对于标准的java Bean 返回的是类自身的实例
而FactoryBean 其返回的对象不一定是自身类的一个实例,返回的是该工厂Bean的getObject方法所返回的对象
一个简单的例子
- public class SayHelloFactoryBeanImpl implements FactoryBean {
- /**
- * 返回该工厂生成的bean
- */
- public Object getObject() throws Exception {
- return new ChinaSayHelloServiceImpl();
- }
- /**
- * getObject返回对象对应的Class
- */
- public Class getObjectType() {
- return ChinaSayHelloServiceImpl.class;
- }
- /**
- * getObject返回的对象 是否是一个单例
- */
- public boolean isSingleton() {
- return false;
- }
- }
- 配置文件
- <bean id="sayHelloFactoryBean" class="com.xx.service.impl.SayHelloFactoryBeanImpl" />
- ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext-server.xml"}, true);
- //bean的 getObject方法 返回的对象
- Object object = context.getBean("sayHelloFactoryBean");
- System.out.println(object);
控制台输出
com.xx.service.impl.ChinaSayHelloServiceImpl@1f66cff
容器返回的是 bean getObject方法返回对象 而不是SayHelloFactoryBeanImpl自身的实例 当然可以用“&”符号转义 获得FactoryBean的自身实例
- ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext-server.xml"}, true);
- //可以用转义符"&"来获得FactoryBean本身实例
- System.out.println(context.getBean("&sayHelloFactoryBean"));
控制台输出
com.xx.service.impl.SayHelloFactoryBeanImpl@75e4fc
下面看看FactoryBean是怎么实现的
Spring FactoryBean接口定义
- public interface FactoryBean {
- Object getObject() throws Exception;
- Class getObjectType();
- boolean isSingleton();
- }
bean的实例化 是在AbstractBeanFactory getBean方法发生的
- public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {
- return doGetBean(name, requiredType, args, false);
- }
- protected Object doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
- // bean name处理 如果是以"&"开头 截取掉
- final String beanName = transformedBeanName(name);
- Object bean = null;
- //单例的bean 只实例化一次 第一次实例化后会放到一个Map中 即singletonObjects map集合中 下次使用的时候直接拿
- Object sharedInstance = getSingleton(beanName);
- if (sharedInstance != null && args == null) {
- // FactoryBean 相关处理 在此方法发生
- //name 调用getBean时传入的参数
- //beanName 截取"&"后的name
- bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
- }
- else {
- ...略
- }
- return bean;
- }
- protected Object getObjectForBeanInstance(
- Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
- // 如果不是FactoryBean的相关调用 结束处理
- //isFactoryDereference 方法判断name 是不是以"&"开始 如果以"&"开始 返回true
- if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
- throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
- }
- if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
- return beanInstance;
- }
- Object object = null;
- //bean的定义为null
- if (mbd == null) {
- //缓存集合factoryBeanObjectCache中包含 当前bean getObject方法返回的实例 不需要在调用 直接返回
- object = getCachedObjectForFactoryBean(beanName);
- }
- if (object == null) {
- FactoryBean factory = (FactoryBean) beanInstance;
- //containsBeanDefinition方法-> bean的定义map beanDefinitionMap集合中 是否包含该bean的定义
- if (mbd == null && containsBeanDefinition(beanName)) {
- mbd = getMergedLocalBeanDefinition(beanName);
- }
- boolean synthetic = (mbd != null && mbd.isSynthetic());
- // FactoryBean getObject触发 并缓存到factoryBeanObjectCache集合中
- object = getObjectFromFactoryBean(factory, beanName, !synthetic);
- }
- return object;
- }
- protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
- //当前的factoryBean是否单例 并且 缓存singletonObjects‘Map中包含FactoryBean的自身实例
- if (factory.isSingleton() && containsSingleton(beanName)) {
- synchronized (getSingletonMutex()) {
- // factoryBeanObjectCache 缓存的是 getObject返回的对象
- Object object = this.factoryBeanObjectCache.get(beanName);
- if (object == null) {
- //getObject方法调用
- object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
- //缓存 getObject方法返回的实例对象
- this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
- }
- return (object != NULL_OBJECT ? object : null);
- }
- }
- else {
- //getObject方法调用
- return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
- }
- }
- private Object doGetObjectFromFactoryBean(
- final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
- throws BeanCreationException {
- AccessControlContext acc = AccessController.getContext();
- return AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- Object object;
- try {
- // getObject方法调用
- object = factory.getObject();
- }
- catch (FactoryBeanNotInitializedException ex) {
- throw new BeanCurrentlyInCreationException(beanName, ex.toString());
- }
- catch (Throwable ex) {
- throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
- }
- if (object == null && isSingletonCurrentlyInCreation(beanName)) {
- throw new BeanCurrentlyInCreationException(
- beanName, "FactoryBean which is currently in creation returned null from getObject");
- }
- if (object != null && shouldPostProcess) {
- try {
- object = postProcessObjectFromFactoryBean(object, beanName);
- }
- catch (Throwable ex) {
- throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
- }
- }
- return object;
- }
- }, acc);
- }
当一个受Spring容器管理的bean 如果实现了FactoryBean接口 在bean实例化(getBean)阶段 Spring会调用该bean的getObejct方法 返回的不一定是自身的实例
Spring 框架中有很多FactoryBean 例如RmiProxyFactoryBean, SqlMapClientFactoryBean. LocalSessionFactoryBean等都是通过FactoryBean getObject方法驱动起来的.对bean的生产 修饰做了很好的封装。
转:Spring FactoryBean源码浅析的更多相关文章
- spring初始化源码浅析之关键类和扩展接口
目录 1.关键接口和类 1.1.关键类之 DefaultListableBeanFactory 1.2.关键类之XmlBeanDefinitionReader 1.3.关键类之ClassPathXml ...
- 【Spring】源码浅析 - ResponseEntity.ok 转载
https://www.jianshu.com/p/1238bfb29ee1 ResponseEntity.ok具体源码
- Spring IOC 源码浅析
控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心. 控制反转一般分为两种类型,依赖注入 ...
- spring源码浅析——IOC
=========================================== 原文链接: spring源码浅析--IOC 转载请注明出处! ======================= ...
- 【原】Spring源码浅析系列-导入源码到Eclipse
用了Spring几年,平时也断断续续在项目里看过一些源码,大多都是比较模糊的,因为一旦从一个地方进去就找不到方向了,只能知道它大概是做了什么事能达到这个功能或者效果,至于细节一般没有太深入去研究.后来 ...
- spring事务源码研读1
转载摘录自:Spring事务源码分析(一)Spring事务入门 有时为了保证一些操作要么都成功,要么都失败,这就需要事务来保证. 传统的jdbc事务如下: @Test public void test ...
- Struts2源码浅析-ConfigurationProvider
ConfigurationProvider接口 主要完成struts配置文件 加载 注册过程 ConfigurationProvider接口定义 public interface Configurat ...
- spring jdbcTemplate源码剖析
本文浅析 spring jdbcTemplate 源码,主要是学习其设计精髓.模板模式.巧妙的回调 一.jdbcTemplate 类结构 ①.JdbcOperations : 接口定义了方法,如 &l ...
- Spring IOC 源码分析
Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...
随机推荐
- Sencha Touch学习(一)
一.Ext的内部类结构示意图 基类Ext.Base 该类是所有通过Ext.define定义出来的类的基类. 是所有Ext类的基石. 来自为知笔记(Wiz)
- BP神经网络的Java实现
http://fantasticinblur.iteye.com/blog/1465497
- 如何使用XE2及更高版本中提供的自定义皮肤(样式)功能
源:如何使用XE2及更高版本中提供的自定义皮肤(样式)功能 1. 制作样式文件: 点击 XE2+ 的 IDE 菜单上的 Tools-->Bitmap Style Designer, 打开设计器. ...
- 使用maven管理后,依然找不到需要的jar包
使用maven管理后,依然报错,找不到,比如如下错误java.lang.ClassNotFoundException: org.springframework.web.context.ContextL ...
- NMEA协议 上位机 C# (转)
源:NMEA协议 上位机 c# 前些时间写做了两款用NMEA协议的上位机,在这里做一个总结和记录.和大家分享,也为了以后不会忘记. NMEA协议总体来说,相对简单,是气象上比较成熟的协议. 主要有以下 ...
- form表单传递下拉框的Value和Text值,不适用Jquery传递
同时获取下拉框的Value和Text值的解决办法:添加一个<input type="text" >文本框,用户选中一项后就将该项的value值给他 然后接受页面获取该文 ...
- laravel memcached使用
当第一次使用cache时,想用 memcached 的方式,但是它直接报错: 说明你的php没安装 memcached 这个扩展,在ubuntu下直接 sudo apt-get install mem ...
- js函数——setinterval和setTimeout
1.window.setTimeout方法 该方法可以延时执行一个函数,例如: <script language="JavaScript" type="text/j ...
- Android之布局大全
Android布局方式可以归类为ViewGroup的5个类别,即ViewGroup的5个直接子类.其它的一些布局都扩展自这5个类. 上结构图: 转自:http://www.cnblogs.com/de ...
- Android布局及属性归总(查询用)
常见布局 LinearLayout 线性布局 子元素任意,组织成一个单一的水平或垂直行,默认为水平方向TableLayout 表格布局 子元素为<Tabl ...