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 ...
随机推荐
- mysql列转行
要得到 SELECT name, SUM(CASE course WHEN '语文' THEN score END ) AS '语文', SUM(CASE course WHEN '数学' THEN ...
- Hadoop 权威指南学习1 (主要框架)
1. Hadoop 最出名的是 MapReduce和 HDFS,不过也有很多其他有用的子项目. 技术栈如下: Core 一系列分布式文件系统和通用I/O的组件和接口(序列化.Java RPC和持久化数 ...
- Java数组操作利器:Arrays工具类
java.util.Arrays提供大量的工具方法来操作数组,这些方法全是静态方法. 1 便捷创建List public static <T> List<T> asList(T ...
- Matlab的实时编辑器(Live Script)
Matlab的实时编辑器(Live Script) 看到伟哥换用了matlab2016a,里面集成了acf行人检测算法,感觉挺好的,索性也从matlab2014a跨越到matlab2016a. 安装后 ...
- waf2控件名
1,查询表格(queryGrid),编辑表格(editGrid) wafGrid 2,快速F7 wafPromptQuick 3,表格F7 wafPromptGrid 4,自定义F7 wafPromp ...
- iOS自动处理键盘事件的第三方库:IQKeyboardManager
我们写界面要考虑很多用户体验问题,键盘事件的响应就是比较麻烦的一种.我们需要监听键盘事件,考虑点击背景收起键盘.考虑键盘遮挡输入框问题等等,而且每个界面都要做这么一套.这个库帮我们解决了这个事情. 这 ...
- jboss性能优化
jboss linux jboss 部署时优化设置: 在/conf/web.xml中通过参数指定: <session-config> <session-ti ...
- 通过rsync搭建一个远程备份系统(一)
前言 我公司是电子商务公司,全部是linux系统,每天的网站数都在增加,为了保证安全,需要建立一个远程容灾系统,将网站数据每天凌晨1点备份到远程服务器上,由于数据量大,每天进行进行增量备份,仅仅备份当 ...
- POJ1426 Find The Multiple (宽搜思想)
Find The Multiple Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 24768 Accepted: 102 ...
- ubuntu14.04设置开机亮度
1 查看自己的系统亮度的最大值: cd /sys/class/backlight 笔记本的显卡型号不同->亮度调节文件夹名会不同. 2 我的是intel_backlight cd intel_b ...