首先要分辨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. MWeb

    专业的 Markdown 写作支持 极简 UI.Dark Mode.漂亮的 Markdown 语法高亮.列表缩进优化,提供 5 种主题选择. 除了支持基本的 Markdown 语法外,还支持大量 Ma ...

  2. 编译hadoop-2.5.2总结

    原文:http://www.cnblogs.com/qigang/p/4194728.html 一.准备的资料 64位linux系统.我使用的是 CentOS JDK 1.7+.注:使用1.7即可,如 ...

  3. Leetcode 98. Validate Binary Search Tree

    Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...

  4. [Poi2000]公共串

    #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> ...

  5. AutoIt3(AU3)开发的智能驱动安装工具,用于系统封装,支持参数静默启动

    项目相关地址 源码:https://github.com/easonjim/Smart_Driver bug提交:https://github.com/easonjim/Smart_Driver

  6. 数据结构算法C语言实现(七)--- 3.1栈的线性实现及应用举例

    一.简述 栈,LIFO.是操作受限的线性表,和线性表一样有两种存储表示方法.下面以顺序存储为例,实现. 二.ADT 暂无. 三.头文件 //3_1.h /** author:zhaoyu email: ...

  7. Objective-C NSData与实现NSCoding协议进行序列化和反序列化

    1.NSData NSData是Objective-C语言中数据的基本类型,其成分可以理解为字节指针和长度的封装的类,来看看源代码 @interface NSData : NSObject <N ...

  8. jackson处理boolean类型的注意点

    在使用jackson处理boolean类型的时候,比如你的java bean有一个boolean类型的字段:isTitle, 默认把这个Java bean 转换为json的时候,这个字段就变成了tit ...

  9. soapUI使用-DataSource获取oracle库中的参数

    soapUI使用-DataSource获取oracle库中的参数 下载mysql和oracle驱动包:http://pan.baidu.com/s/1i3sy1MH 放在Program Files\S ...

  10. 用css3实现各种图标效果(1)

    公共样式 应该说现在绝大多数公司的项目前端都是一团乱,不仅仅是js写的没有任何框架而言,css同样也是如此,导致项目如果要升级或者说有新的变更维护起来就特别困难. 最近领导决定花大时间整理一下css样 ...