首先是BeanFactory和FactoryBean的区别:
- FactoryBean:是一个Java Bean,但是它是一个能生产对象的工厂Bean,它的实现和工厂模式及修饰器模式很像。比如下:我们把bean比作猪,那么FactoryBean可以算是一个母猪,首先它本身也是一只猪,但它能够下小猪。
- BeanFactory:这就是一个Factory,是一个IOC容器或者叫对象工厂,它里面存着很多的bean。还用上面那个比如:如果bean是猪,那么它可以理解成猪圈,猪圈里面有很
FactoryBean的核心就在于通过getObject方法可以获取的是它所生产的对象
实现FactoryBean 必须实现接口的3个方法:getObject、getObjectType、isSingleton
使用FactoryBean的场景有两个:1、创建代理对象 2、通过xml配置方式比较繁琐或有难度,那么可以通过FactoryBean 在java代码里面配置bean
网上找了两个例子,说明这两点
1.创建代理对象的例子:
ZFFactoryBean
1 package com.spring.factorybean; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 7 import org.springframework.beans.factory.DisposableBean; 8 import org.springframework.beans.factory.FactoryBean; 9 import org.springframework.beans.factory.InitializingBean; 10 11 public class ZFFactoryBean implements FactoryBean<Object>, InitializingBean, DisposableBean { 12 13 // 被代理对象实现的接口名(在使用Proxy时需要用到,用于决定生成的代理对象类型) 14 private String interfaceName; 15 16 // 被代理的对象 17 private Object target; 18 19 // 生成的代理对象 20 private Object proxyObj; 21 22 public void destroy() throws Exception { 23 System.out.println("distory..."); 24 } 25 26 public void afterPropertiesSet() throws Exception { 27 28 proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(), 29 new Class[] { Class.forName(interfaceName) }, new InvocationHandler() { 30 31 public Object invoke(Object proxy, Method method, Object[] args) 32 throws Throwable { 33 System.out.println("method:" + method.getName()); 34 System.out.println("Method before..."); 35 Object result = method.invoke(target, args); 36 System.out.println("Method after..."); 37 return result; 38 } 39 }); 40 41 System.out.println("afterPropertiesSet"); 42 } 43 44 public Object getObject() throws Exception { 45 System.out.println("getObject"); 46 return proxyObj; 47 } 48 49 public Class<?> getObjectType() { 50 return proxyObj == null ? Object.class : proxyObj.getClass(); 51 } 52 53 public boolean isSingleton() { 54 return true; 55 } 56 57 public String getInterfaceName() { 58 return interfaceName; 59 } 60 61 public void setInterfaceName(String interfaceName) { 62 this.interfaceName = interfaceName; 63 } 64 65 public Object getTarget() { 66 return target; 67 } 68 69 public void setTarget(Object target) { 70 this.target = target; 71 } 72 73 }
PersonService 和 PersonServiceImpl的代码此处省略
xml配置:
1 <bean id="personService" class="com.spring.service.impl.PersonServiceImpl" scope="prototype"> 2 <property name="name" value="is_zhoufeng" /> 3 </bean> 4 5 <bean id="zfPersonService" class="com.spring.factorybean.ZFFactoryBean"> 6 <property name="interfaceName" value="com.spring.service.PersonService" /> 7 <property name="target" ref="personService"/> 8 </bean>
用法:
1 @Test 2 public void test06() { 3 PersonService ps = context.getBean("zfPersonService", PersonService.class); 4 5 ps.sayHello(); 6 7 String name = ps.getName(); 8 9 System.out.println(name); 10 }
2.配置较为复杂的bean
Person类,get set省略
1 public class Person { 2 private String name; 3 private String address; 4 private int age; 5 }
如果用xml配置,如下,会比较麻烦:
1 <bean id="personBean" class="com.gh.MavenTest.Person"> 2 <property name="name" value="gh1" /> 3 <property name="address" value="address1" /> 4 <property name="age" value="28" /> 5 </bean>
换成FactoryBean的方式配置:
1 public class PersonFactoryBean implements FactoryBean<Person>{ 2 3 private String personInfo; 4 5 public Person getObject() throws Exception { 6 Person person = new Person () ; 7 String [] infos = personInfo.split ( "," ) ; 8 person.setName(infos[0]); 9 person.setAddress(infos[1]); 10 person.setAge(Integer.parseInt(infos[2])); 11 return person; 12 } 13 14 public Class<Person> getObjectType() { 15 return Person.class; 16 } 17 18 public boolean isSingleton() { 19 return true; 20 } 21 }
xml再配置一下:
1 <bean id="personFactory" class="com.hik.MavenTest.PersonFactory"> 2 <property name="personInfo" value="gh2,address2,22"></property> 3 </bean>
那么这个时候我们getBean("personFactory")得到的就是Person对象而不是PersonFactoryBean对象
如果要取到PersonFactoryBean这个bean, 在beanName前面加上&,即getBean("&personFactory")
spring自带了不少FactoryBean的实现,最下面是我们所在的公司的实现
具体使用的时候,还可以用FactoryBean创建多个bean
1 <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" /> 2 <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" /> 3 <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" /> 4 <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" /> 5 <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />