首先要分辨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. 【CodeForces 567E】President and Roads(最短路)

    Description Berland has n cities, the capital is located in city s, and the historic home town of th ...

  2. Yii2的View中JS代码添加

    直接写 <script> $(function(){ alert("aaa"); }); <script> 会提示出错 是因为view中添加js代码的前面没 ...

  3. 【bzoj1178】 Apio2009—CONVENTION会议中心

    http://www.lydsy.com/JudgeOnline/problem.php?id=1178 (题目链接) 题意 给出n个区间,问在区间两两不相交的情况下最多能选出多少区间,并输出字典序最 ...

  4. 针对CMS中的tag标签理解

    针对CMS的tag标签有以下解释: 什么tag标签? TAG标签是一种由自定义的一种标签,要比分类更加的准确,可以概括文章主要内容的关键词. 运用TAG标签,可以使网站的文章更容易被搜索引擎检索到.百 ...

  5. eclipse crash

    SIGSEGV (0xb) at pc=0x00007fbcae8f2c91, pid=5707, tid=140449979574016 JRE version: 7.0_25-b30 Java V ...

  6. 主机宝(zhujibao) /a/apps/zhujibao/manager/apps/config/config.php no-password Login Vulnerabilities Based On Default cookie Verification From Default File

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 主机宝管理程序使用了CodeIgniter框架,要想在CodeIgnit ...

  7. win7下firefox浏览器不能使用

    win7下firefox浏览器不能使用,只有360浏览器才能使用. 使用360安全卫士,到更多工具里面选择"LSP修复",就可以了. 原来是因为安装了土豆加速,然后卸载导致的. 看 ...

  8. Swift 函数做参数和闭包做参数的一个细节差别

    函数作参数,示例为传入一个String和一个添加前缀的函数,返回一个添加完前缀的String: func demo(str:String,addPrefix:(String)->String)- ...

  9. pom中定义某jar包的依赖,但并不使用该jar包,那最后部署的应用中会有这个jar包么?

    关于这个问题,首先得明确这个jar包的依赖是怎么定义的,我们知道在maven的pom文件中,会有:dependencymanagement和dependency2个部分   一般我们说在depende ...

  10. AngularJs $compile编译服务与指令

    $compile 这是个编译服务.编译一段HTML字符串或者DOM的模板, 产生一个将scope和模板连接到一起的函数. 编译服务主要是为指令编译DOM元素,下面的一大段也是主要介绍指令的. 下面是一 ...