简介 传统的Spring容器加载一个Bean的整个过程,都是由Spring控制的,换句话说,开发者除了设置Bean相关属性之外,是没有太多的自主权的。FactoryBean改变了这一点,开发者可以个性化地定制自己想要实例化出来的Bean,方法就是实现FactoryBean接口。
FactoryBean接口 1 2 3 4 5 6 7 8 9 10 11 package org.springframework.beans.factory; public interface FactoryBean<T> { //返回生成的实例对象 T getObject() throws Exception; //返回生成bean实例的class类型 Class<?> getObjectType(); //返回是否为单例 boolean isSingleton(); }
自定义bean 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 //Animal接口 public interface Animal { public String sayHello(); } //cat实现 public class Cat implements Animal { @Override public String sayHello() { return "Hello cat"; } } //tiger实现 public class Tiger implements Animal { @Override public String sayHello() { return "hello tiger"; } } //生产animal的工厂bean public class AnimalFactoryBean implements FactoryBean<Animal> { //注入类型 private String name; public void setName(String name) { this.name = name; } //根据类型生产相应实例 @Override public Animal getObject() throws Exception { if (name.equals("tiger")) { return new Tiger(); } else if(name.equals("cat")) { return new Cat(); } return null; } @Override public Class<?> getObjectType() { return Animal.class; } @Override public boolean isSingleton() { return true; } }
配置 返回的实例不是AnimalFactoryBean的实例,而是AnimalFactoryBean中的getObject()方法返回的对象
1 2 3 <bean id="animalFactoryBean" class="com.fuyi.test.factorybean.AnimalFactoryBean"> <property name="name" value="cat"/> </bean>
测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package com.fuyi.test; import org.junit.Before; import org.junit.Test; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.fuyi.test.aware.AwareBean; import com.fuyi.test.factorybean.Animal; import com.fuyi.test.factorybean.AnimalFactoryBean; import com.fuyi.test.lifecycle.Foobar; public class BeanTest { AbstractApplicationContext ac; @Before public void init() { ac = new ClassPathXmlApplicationContext("classpath:bean.xml"); //基于web的ApplicationContext会自动在web应用关闭时,自动关闭IOC容器 //非web时,可以在JVM中注册一个“关闭钩子”,确保IOC容器被恰当关闭,单例bean持有的资源被释放,回调destory()方法 ac.registerShutdownHook(); ac.start(); } @Test public void testFactoryBean() { Animal bean = ac.getBean(Animal.class); String sayHello = bean.sayHello(); System.out.println(sayHello); } } //执行结果:Hello cat