Spring之FactoryBean
首先要分辨BeanFactory 与 FactoryBean的区别, 两个名字很像,所以容易搞混
BeanFactory: 以Factory结尾,表示它是一个工厂类,是用于管理Bean的一个工厂
FactoryBean:以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean<T>接 口的Bean,根据该Bean的Id从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是 FactoryBean本身, 如果要获取FactoryBean对象,可以在id前面加一个&符号来获取。
Spring中的Bean有两种。
一种是普通的bean ,比如配置
- <bean id="personService" class="com.spring.service.impl.PersonServiceImpl" scope="prototype">
- <property name="name" value="is_zhoufeng" />
- </bean>
那个使用BeanFactory根据id personService获取bean的时候,得到的对象就是PersonServiceImpl类型的。
另外一种就是实现了org.springframework.beans.factory.FactoryBean<T>接口的
Bean ,
那么在从BeanFactory中根据定义的id获取bean的时候,获取的实际上是FactoryBean接口中的getObject()方法返回的对
象。
以Spring提供的ProxyFactoryBean为例子,配置如下:
- <bean id="personServiceByLog" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="proxyInterfaces">
- <list>
- <value>com.spring.service.PersonService</value>
- </list>
- </property>
- <property name="interceptorNames">
- <list>
- <value>logInteceptor</value>
- <value>ZFMethodAdvice</value>
- </list>
- </property>
- <property name="targetName" value="personService" />
- </bean>
那么在代码中根据personServiceByLog来获取的Bean实际上是PersonService类型的。
- @Test
- public void test01() {
- PersonService ps = context.getBean("personService", PersonService.class);
- ps.sayHello();
- String name = ps.getName();
- System.out.println(name);
- }
如果要获取ProxyFactoryBean本身,可以如下
- @Test
- public void test04() {
- ProxyFactoryBean factoryBean = context.getBean("&personServiceByLog", ProxyFactoryBean.class);
- PersonService ps = (PersonService) factoryBean.getObject();
- String name = ps.getName();
- System.out.println(name);
- }
自己实现一个FactoryBean, 功能:用来代理一个对象,对该对象的所有方法做一个拦截,在方法调用前后都输出一行log
- package com.spring.factorybean;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- import org.springframework.beans.factory.DisposableBean;
- import org.springframework.beans.factory.FactoryBean;
- import org.springframework.beans.factory.InitializingBean;
- public class ZFFactoryBean implements FactoryBean<Object>, InitializingBean, DisposableBean {
- // 被代理对象实现的接口名(在使用Proxy时需要用到,用于决定生成的代理对象类型)
- private String interfaceName;
- // 被代理的对象
- private Object target;
- // 生成的代理对象
- private Object proxyObj;
- public void destroy() throws Exception {
- System.out.println("distory...");
- }
- public void afterPropertiesSet() throws Exception {
- proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(),
- new Class[] { Class.forName(interfaceName) }, new InvocationHandler() {
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- System.out.println("method:" + method.getName());
- System.out.println("Method before...");
- Object result = method.invoke(target, args);
- System.out.println("Method after...");
- return result;
- }
- });
- System.out.println("afterPropertiesSet");
- }
- public Object getObject() throws Exception {
- System.out.println("getObject");
- return proxyObj;
- }
- public Class<?> getObjectType() {
- return proxyObj == null ? Object.class : proxyObj.getClass();
- }
- public boolean isSingleton() {
- return true;
- }
- public String getInterfaceName() {
- return interfaceName;
- }
- public void setInterfaceName(String interfaceName) {
- this.interfaceName = interfaceName;
- }
- public Object getTarget() {
- return target;
- }
- public void setTarget(Object target) {
- this.target = target;
- }
- }
然后来试试:
首先这样定义bean
- <bean id="personService" class="com.spring.service.impl.PersonServiceImpl" scope="prototype">
- <property name="name" value="is_zhoufeng" />
- </bean>
- <bean id="zfPersonService" class="com.spring.factorybean.ZFFactoryBean">
- <property name="interfaceName" value="com.spring.service.PersonService" />
- <property name="target" ref="personService"/>
- </bean>
然后获取Bean,并测试。
- @Test
- public void test06() {
- PersonService ps = context.getBean("zfPersonService", PersonService.class);
- ps.sayHello();
- String name = ps.getName();
- System.out.println(name);
- }
会发现sayHello与getName方法调用前后都有log打印。
上面的ZFBeanFactory只是模仿了ProxyFactoryBean的功能做了一个实现而已。
其实通过FactoryBean这种特点,可以实现很多有用的功能 。。。
原文:http://blog.csdn.net/is_zhoufeng/article/details/38422549
Spring之FactoryBean的更多相关文章
- 聊聊Spring的FactoryBean其实没那么难
前言 谈到Spring的FactoryBean,就会知道Spring中经典的面试题:FactoryBean和BeanFactory的区别.我们这里就简单概括下: . BeanFactory是接口,提供 ...
- Spring错误——Spring 注解——factory-bean reference points back to the same bean definition
背景:学习Spring,在使用注解@Bean的name属性配置<bean>实例时,不能注册实例成功 报错 WARNING: Exception encountered during con ...
- Spring的FactoryBean使用
Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean.工厂Bean跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂Bean的g ...
- spring 之 factory-bean & factory-method
这两者常常是一起出现的,或者说他们经常是一起被使用的.但是其实是分为了两种情况: 1 同时使用factory-bean 和 factory-method 如果,我们在一个bean 元素上同时配置 fa ...
- spring的FactoryBean
(以下内容翻译自spring/docs/3.2.18.RELEASE) 为具有工厂属性的对象实现FactoryBean接口. FactoryBean接口是spring IoC 容器实例化逻辑的一点补充 ...
- Spring中FactoryBean与BeanFactory的区别
版本:spring-framework-4.1 一概述 BeanFactory 与 FactoryBean的区别, 两个名字很像,面试中也经常遇到,所以容易搞混,现从源码以及示例两方面来分析. 二.源 ...
- Spring中FactoryBean的作用和实现原理
BeanFactory与FactoryBean,相信很多刚翻看Spring源码的同学跟我一样很好奇这俩货怎么长得这么像,分别都是干啥用的.BeanFactory是Spring中Bean工厂的顶层接口, ...
- 【带你手撸Spring】没有哪个框架开发,能离开 Spring 的 FactoryBean!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 老司机,你的砖怎么搬的那么快? 是有劲?是技巧?是后门?总之,那个老司机的代码总是可 ...
- Spring 通过FactoryBean配置Bean
1.实现FactoryBean接口 import org.springframework.beans.factory.FactoryBean; public class CarFactoryBean ...
随机推荐
- skiing
package noj_skiing; import java.util.*; import java.math.*; public class Main { public static void m ...
- Mysql实现行列转换
前言: 最近又玩起了sql语句,想着想着便给自己出了一道题目:“行列转换”.起初瞎折腾了不少时间也上网参考了一些博文,不过大多数是采用oracle数据库当中的一些便捷函数进行处理,比如”pivot”. ...
- 运行python代码报错UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 91: ordinal not in range(128)的解决办法
1.通过搜集网上的资料,自己多次尝试,问题算是解决了,在代码中加上如下几句即可: import sys reload(sys) sys.setdefaultencoding('utf-8') 2.原因 ...
- Leetcode 95. Unique Binary Search Tree II
由于BST的性质,所以右子树或者左子树中Node的值是连续的: 左子树 = [1, i -1], root = i, 右子树 = [i + 1, n].使用一个递归函数构造这个BST.其中返回值应该是 ...
- spring的自动装配基础
当开始看别人的代码使用注解的时候,以为照着别人的代码写,也写一个注释就能实现这样的功能,但是,现在开始考虑自动装配时怎样实现的. 首先,如果如果知道如何手动在xml配置中"装配bean&qu ...
- 何解決 LinqToExcel 發生「無法載入檔案或組件」問題何解決 LinqToExcel 發生「無法載入檔案或組件」問題
在自己的主機上透過 Visual Studio 2013 與 IISExpress 開發與測試都還正常,但只要部署到測試機或正式機,就是沒辦法順利執行,卡關許久之後找我協助.我發現錯誤訊息確實很「一般 ...
- hdu5124 线段树+离散化
题意:令a[l..r]都+1,求a[1..n]的最大值 裸的成段更新+区间最值,但是本题坐标范围很大(10^9),所以需要离散化 顺便离散化模板get 离散化的基本思路: 设一共有m个数,范围1--n ...
- 企业应用系统设计分享PPT
因今天上午需要为团队做一个分享,所以昨晚连夜写了一个<企业应用系统设计>的PPT,因为时间比较短,写的比较急.现在把PPT贴出来,做一个记录.同时也希望对大家有用. 文件我上传到了百度网盘 ...
- Linux之:Ubuntu速学笔记(2)
撰写日期:2016-7-3 18:20:39 基本内容包括:Flash player安装.编译安装PHP.写个简单的PHP程序:Java程序(Java需要使用“javac”命令编译一下才能执行) 一. ...
- Linux/UNIX 定时任务 cron 详解
定时任务( job)被用于安排那些需要被周期性执行的命令.利用它,你可以配置某些命令或者脚本,让它们在某个设定的时间内周期性地运行.cron 是 Linux 或者类 Unix 系统中最为实用的工具之一 ...