Spring容器扩展之FactoryBean
FactoryBean接口是Spring IoC容器实例化逻辑的扩展点。
一、区别FactoryBean和BeanFactory
首先不要混淆FactoryBean和BeanFactory。
BeanFactory直译是生产Bean的工厂,在Srping中就是容器,常用的ApplicationContext就是它的一个继承类。我们也可以直接使用BeanFactory示例:
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("/psring-config.xml"));
而FactoryBea只是一个bean,只不过比较特殊
二、区别FactoryBean和普通Bean
Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean即FactoryBean,这两种Bean都被容器管理。
工厂Bean是实现了org.springframework.beans.factory.FactoryBean<T>接口的Bean,从ApplicationContext的getBean()方法获取的对象不是该类的一个实例,而是该类的getObject()方法所返回的对象。
当我们需要获取FactoryBean实例本身而不是它所产生的bean,则要使用&符号。
比如,现有FactoryBean,id为”myBean”,在容器上调用getBean("myBean")将返回FactoryBean产生的bean。调用getBean("&myBean")将返回FactoryBean它本身的实例。
例如:如果使用传统方式配置下面Car的<bean>时,Car的每个属性分别对应一个<property>元素标签。
package com.spring.model;
public class Car {
private int maxSpeed;
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
private String brand;
private double price;
}
如果用FactoryBean的方式实现就会灵活一些,下例通过逗号分割符的方式一次性地为Car的所有属性指定配置值:
public class CarFactoryBean implements FactoryBean<Car> {
private String carInfo ;
public Car getObject () throws Exception {
Car car = new Car () ;
String [] infos = carInfo .split ( "," ) ;
car.setBrand ( infos [ 0 ]) ;
car.setMaxSpeed ( Integer. valueOf ( infos [ 1 ])) ;
car.setPrice ( Double. valueOf ( infos [ 2 ])) ;
return car;
}
public Class<Car> getObjectType () {
return Car. class ;
}
public boolean isSingleton () {
return false ;
}
public String getCarInfo () {
return this . carInfo ;
}
// 接受逗号分割符设置属性信息
public void setCarInfo ( String carInfo ) {
this . carInfocarInfo = carInfo;
}
}
package com.spring.main;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.spring.model.Car;
import com.spring.model.Person;
import com.spring.model.Student;
public class Demoapp {
public static void main(String[] args) {
// Reading configuration from the spring configuration file.
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// Person myperson = context.getBean("personBean", Person.class);
// Student student = context.getBean("student", Student.class);
// System.out.println("student id= " + student.getId());
// System.out.println("Name= " + myperson.getName());
Car car = context.getBean("car", Car.class);
System.out.println("[car]"+car.toString());
// Closing the context object.
context.close();
}
}
xml配置
<bean id="car" class="com.spring.bean.CarFactoryBean">
<property name="carInfo" value=" 超级跑车,400,2000000"></property>
</bean>
输出如下:
Constructor of person bean is invoked!
Bean 'personBean' before created : com.spring.model.Person@7cd62f43
Initializing method of person bean is invoked!
Custom initializing method of person bean is invoked!
Bean 'personBean' created : com.spring.model.Person@7cd62f43
Bean 'student' before created : com.spring.model.Student@6d4b1c02
Bean 'student' created : com.spring.model.Student@6d4b1c02
Bean 'car' before created : com.spring.bean.CarFactoryBean@4667ae56
Bean 'car' created : com.spring.bean.CarFactoryBean@4667ae56
Bean 'car' created : Car [maxSpeed=400, brand= 超级跑车, price=2000000.0]
[car]Car [maxSpeed=400, brand= 超级跑车, price=2000000.0]
Destroy method of person bean is invoked!
Custom destroy method of person bean is invoked!