首先要分辨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. mysql列转行

    要得到 SELECT name, SUM(CASE course WHEN '语文' THEN score END ) AS '语文', SUM(CASE course WHEN '数学' THEN ...

  2. Hadoop 权威指南学习1 (主要框架)

    1. Hadoop 最出名的是 MapReduce和 HDFS,不过也有很多其他有用的子项目. 技术栈如下: Core 一系列分布式文件系统和通用I/O的组件和接口(序列化.Java RPC和持久化数 ...

  3. Java数组操作利器:Arrays工具类

    java.util.Arrays提供大量的工具方法来操作数组,这些方法全是静态方法. 1 便捷创建List public static <T> List<T> asList(T ...

  4. Matlab的实时编辑器(Live Script)

    Matlab的实时编辑器(Live Script) 看到伟哥换用了matlab2016a,里面集成了acf行人检测算法,感觉挺好的,索性也从matlab2014a跨越到matlab2016a. 安装后 ...

  5. waf2控件名

    1,查询表格(queryGrid),编辑表格(editGrid) wafGrid 2,快速F7 wafPromptQuick 3,表格F7 wafPromptGrid 4,自定义F7 wafPromp ...

  6. iOS自动处理键盘事件的第三方库:IQKeyboardManager

    我们写界面要考虑很多用户体验问题,键盘事件的响应就是比较麻烦的一种.我们需要监听键盘事件,考虑点击背景收起键盘.考虑键盘遮挡输入框问题等等,而且每个界面都要做这么一套.这个库帮我们解决了这个事情. 这 ...

  7. jboss性能优化

    jboss     linux jboss 部署时优化设置: 在/conf/web.xml中通过参数指定: <session-config>          <session-ti ...

  8. 通过rsync搭建一个远程备份系统(一)

    前言 我公司是电子商务公司,全部是linux系统,每天的网站数都在增加,为了保证安全,需要建立一个远程容灾系统,将网站数据每天凌晨1点备份到远程服务器上,由于数据量大,每天进行进行增量备份,仅仅备份当 ...

  9. POJ1426 Find The Multiple (宽搜思想)

    Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24768   Accepted: 102 ...

  10. ubuntu14.04设置开机亮度

    1 查看自己的系统亮度的最大值: cd /sys/class/backlight 笔记本的显卡型号不同->亮度调节文件夹名会不同. 2 我的是intel_backlight cd intel_b ...