首先要分辨BeanFactory 与 FactoryBean的区别, 两个名字很像,所以容易搞混

BeanFactory: 以Factory结尾,表示它是一个工厂类,是用于管理Bean的一个工厂

FactoryBean:以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean<T>接 口的Bean,根据该Bean的Id从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是 FactoryBean本身, 如果要获取FactoryBean对象,可以在id前面加一个&符号来获取。

Spring中的Bean有两种。

一种是普通的bean ,比如配置

  1. <bean id="personService" class="com.spring.service.impl.PersonServiceImpl" scope="prototype">
  2. <property name="name" value="is_zhoufeng" />
  3. </bean>

那个使用BeanFactory根据id personService获取bean的时候,得到的对象就是PersonServiceImpl类型的。

另外一种就是实现了org.springframework.beans.factory.FactoryBean<T>接口的
Bean ,
那么在从BeanFactory中根据定义的id获取bean的时候,获取的实际上是FactoryBean接口中的getObject()方法返回的对
象。

以Spring提供的ProxyFactoryBean为例子,配置如下:

  1. <bean id="personServiceByLog" class="org.springframework.aop.framework.ProxyFactoryBean">
  2. <property name="proxyInterfaces">
  3. <list>
  4. <value>com.spring.service.PersonService</value>
  5. </list>
  6. </property>
  7. <property name="interceptorNames">
  8. <list>
  9. <value>logInteceptor</value>
  10. <value>ZFMethodAdvice</value>
  11. </list>
  12. </property>
  13. <property name="targetName" value="personService" />
  14. </bean>

那么在代码中根据personServiceByLog来获取的Bean实际上是PersonService类型的。

  1. @Test
  2. public void test01() {
  3. PersonService ps = context.getBean("personService", PersonService.class);
  4. ps.sayHello();
  5. String name = ps.getName();
  6. System.out.println(name);
  7. }

如果要获取ProxyFactoryBean本身,可以如下

  1. @Test
  2. public void test04() {
  3. ProxyFactoryBean factoryBean = context.getBean("&personServiceByLog", ProxyFactoryBean.class);
  4. PersonService ps = (PersonService) factoryBean.getObject();
  5. String name = ps.getName();
  6. System.out.println(name);
  7. }

自己实现一个FactoryBean, 功能:用来代理一个对象,对该对象的所有方法做一个拦截,在方法调用前后都输出一行log

  1. package com.spring.factorybean;
  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.Method;
  4. import java.lang.reflect.Proxy;
  5. import org.springframework.beans.factory.DisposableBean;
  6. import org.springframework.beans.factory.FactoryBean;
  7. import org.springframework.beans.factory.InitializingBean;
  8. public class ZFFactoryBean implements FactoryBean<Object>, InitializingBean, DisposableBean {
  9. // 被代理对象实现的接口名(在使用Proxy时需要用到,用于决定生成的代理对象类型)
  10. private String interfaceName;
  11. // 被代理的对象
  12. private Object target;
  13. // 生成的代理对象
  14. private Object proxyObj;
  15. public void destroy() throws Exception {
  16. System.out.println("distory...");
  17. }
  18. public void afterPropertiesSet() throws Exception {
  19. proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(),
  20. new Class[] { Class.forName(interfaceName) }, new InvocationHandler() {
  21. public Object invoke(Object proxy, Method method, Object[] args)
  22. throws Throwable {
  23. System.out.println("method:" + method.getName());
  24. System.out.println("Method before...");
  25. Object result = method.invoke(target, args);
  26. System.out.println("Method after...");
  27. return result;
  28. }
  29. });
  30. System.out.println("afterPropertiesSet");
  31. }
  32. public Object getObject() throws Exception {
  33. System.out.println("getObject");
  34. return proxyObj;
  35. }
  36. public Class<?> getObjectType() {
  37. return proxyObj == null ? Object.class : proxyObj.getClass();
  38. }
  39. public boolean isSingleton() {
  40. return true;
  41. }
  42. public String getInterfaceName() {
  43. return interfaceName;
  44. }
  45. public void setInterfaceName(String interfaceName) {
  46. this.interfaceName = interfaceName;
  47. }
  48. public Object getTarget() {
  49. return target;
  50. }
  51. public void setTarget(Object target) {
  52. this.target = target;
  53. }
  54. }

然后来试试:

首先这样定义bean

  1. <bean id="personService" class="com.spring.service.impl.PersonServiceImpl" scope="prototype">
  2. <property name="name" value="is_zhoufeng" />
  3. </bean>
  4. <bean id="zfPersonService" class="com.spring.factorybean.ZFFactoryBean">
  5. <property name="interfaceName" value="com.spring.service.PersonService" />
  6. <property name="target"  ref="personService"/>
  7. </bean>

然后获取Bean,并测试。

  1. @Test
  2. public void test06() {
  3. PersonService ps = context.getBean("zfPersonService", PersonService.class);
  4. ps.sayHello();
  5. String name = ps.getName();
  6. System.out.println(name);
  7. }

会发现sayHello与getName方法调用前后都有log打印。

上面的ZFBeanFactory只是模仿了ProxyFactoryBean的功能做了一个实现而已。

其实通过FactoryBean这种特点,可以实现很多有用的功能 。。。

原文:http://blog.csdn.net/is_zhoufeng/article/details/38422549

Spring之FactoryBean的更多相关文章

  1. 聊聊Spring的FactoryBean其实没那么难

    前言 谈到Spring的FactoryBean,就会知道Spring中经典的面试题:FactoryBean和BeanFactory的区别.我们这里就简单概括下: . BeanFactory是接口,提供 ...

  2. Spring错误——Spring 注解——factory-bean reference points back to the same bean definition

    背景:学习Spring,在使用注解@Bean的name属性配置<bean>实例时,不能注册实例成功 报错 WARNING: Exception encountered during con ...

  3. Spring的FactoryBean使用

     Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean.工厂Bean跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂Bean的g ...

  4. spring 之 factory-bean & factory-method

    这两者常常是一起出现的,或者说他们经常是一起被使用的.但是其实是分为了两种情况: 1 同时使用factory-bean 和 factory-method 如果,我们在一个bean 元素上同时配置 fa ...

  5. spring的FactoryBean

    (以下内容翻译自spring/docs/3.2.18.RELEASE) 为具有工厂属性的对象实现FactoryBean接口. FactoryBean接口是spring IoC 容器实例化逻辑的一点补充 ...

  6. Spring中FactoryBean与BeanFactory的区别

    版本:spring-framework-4.1 一概述 BeanFactory 与 FactoryBean的区别, 两个名字很像,面试中也经常遇到,所以容易搞混,现从源码以及示例两方面来分析. 二.源 ...

  7. Spring中FactoryBean的作用和实现原理

    BeanFactory与FactoryBean,相信很多刚翻看Spring源码的同学跟我一样很好奇这俩货怎么长得这么像,分别都是干啥用的.BeanFactory是Spring中Bean工厂的顶层接口, ...

  8. 【带你手撸Spring】没有哪个框架开发,能离开 Spring 的 FactoryBean!

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 老司机,你的砖怎么搬的那么快? 是有劲?是技巧?是后门?总之,那个老司机的代码总是可 ...

  9. Spring 通过FactoryBean配置Bean

    1.实现FactoryBean接口 import org.springframework.beans.factory.FactoryBean; public class CarFactoryBean ...

随机推荐

  1. highchart去掉highcharts.com及导出

    右下角默认会有highcharts.com credits: { enabled:false} 导出服务用于Highcharts导出功能,即通过导出服务器将图表导出为常见图片格式或 PDF 文档. 默 ...

  2. Java反序列化测试

    前言:有没有想过,如何将对象进行“加密”后写入磁盘?序列化帮你实现! 1.概念 序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写 ...

  3. Cocoa pod的使用注意点

    一.CocoaPods是什么? CocoaPods是一个负责管理iOS项目中第三方开源库的工具.CocoaPods的项目源码在Github上管理.该项目开始于2011年8月12日,在这两年多的时间里, ...

  4. double截取小数点位数

    (double)decimal.Round(decimal.Parse((planVoSt.TotalCompleteAmount / planVoSt.TotalUserCount).ToStrin ...

  5. [bzoj1009][HNOI2008]GT考试

    Description 阿申准备报名参加考试,准考证号为位数,他不希望准考证号上出现不吉利的数字. 他的不吉利数学有位,不出现是指中没有恰好一段等于. 可以为. Input 第一行输入.接下来一行输入 ...

  6. Flipping Bits in Memory Without Accessing Them: An Experimental Study of DRAM Disturbance Errors

    目录 . Rowhammer Introduction . Rowhammer Principle . Track And Fix 1.  rowhammer introduction 今天的DRAM ...

  7. 浅析初等贪吃蛇AI算法

    作为小学期程序设计训练大作业的一部分,也是自己之前思考过的一个问题,终于利用小学期完成了贪吃蛇AI的一次尝试,下作一总结. 背景介绍: 首先,我针对贪吃蛇AI这一关键词在百度和google上尽心了检索 ...

  8. ClassCastException 导致程序一运行就强制退出

    程序显示是类型转换异常,原因是  ic—launcher 不是layerlist图形,而是bmp类型(此处不是指格式)图片,因此取出来后经过红框内强制类型转换导致出错. 为什么我当时要把他强制转换? ...

  9. .net中ckeditor的应用

    ①js文件的引入 <script src="/public/ckeditor_4.4.7/ckeditor.js"></script> <script ...

  10. Linux下安装部署Java

    Java安装6小部(适合新手) 1.下载软件包 # wget http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x ...