簡介
創(chuàng)建對象最簡單的方式是直接使用new操作符传货,如果創(chuàng)建對象比較繁雜,可以采用工廠模式。同樣Spring中提供了FactoryBean接口來幫助創(chuàng)建對象。
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
- T getObject():返回由FactoryBean創(chuàng)建的bean實(shí)例肄满。bean示例可能是singleton還是prototype取決于isSingleton方法的返回。
- boolean isSingleton():返回由FactoryBean創(chuàng)建的bean實(shí)例的作用域是singleton還是prototype。
- Class<T> getObjectType():返回FactoryBean創(chuàng)建的bean類型稠歉。
在Spring中掰担,創(chuàng)建bean時(shí),如果該bean實(shí)現(xiàn)了FactoryBean接口轧抗,那么就會(huì)調(diào)用getObject方法獲取真正的bean恩敌, 通過 getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的bean横媚。如果想要獲取FactoryBean本身纠炮,在beanName前顯示的加上 "&" 前綴, 例如getBean("&myBean")。
用途:
Spring代理
Spring代理的實(shí)現(xiàn)類ProxyFactoryBean灯蝴,當(dāng)實(shí)例化ProxyFactoryBean時(shí)恢口,對原有的singletonInstance對象進(jìn)行封裝,返回的是一個(gè)代理對象穷躁。Spring常用的AOP耕肩,以及事務(wù)注解都是基于Spring代理實(shí)現(xiàn)。
public class ProxyFactoryBean extends ProxyCreatorSupport implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {
@Nullable
private Object singletonInstance; //原有對象
@Nullable
public Object getObject() throws BeansException {
this.initializeAdvisorChain();
if (this.isSingleton()) {
return this.getSingletonInstance();
} else {
if (this.targetName == null) {
this.logger.info("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property.");
}
return this.newPrototypeInstance(); //返回代理后的對象
}
}
public Class<?> getObjectType() {
synchronized(this) {
if (this.singletonInstance != null) {
return this.singletonInstance.getClass();
}
}
Class<?>[] ifcs = this.getProxiedInterfaces();
if (ifcs.length == 1) {
return ifcs[0];
} else if (ifcs.length > 1) {
return this.createCompositeInterface(ifcs);
} else {
return this.targetName != null && this.beanFactory != null ? this.beanFactory.getType(this.targetName) : this.getTargetClass();
}
}
public boolean isSingleton() {
return this.singleton;
}
}
2.自定義bean工廠創(chuàng)建方法
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;
}
}
配置文件添加
<bean id="car" class="com.test.factorybean.CarFactoryBean" carInfo="大眾SUV,180,180000"/>
當(dāng)調(diào)用getBean("car") 時(shí)问潭,Spring會(huì)去調(diào)用getObject方法猿诸,獲取的是Car對象,調(diào)用getBean("&car") 時(shí)狡忙,獲取的是該CarFactoryBean示例梳虽。
參考:
[1].https://docs.spring.io/spring-framework/docs/4.3.15.RELEASE/spring-framework-reference/htmlsingle/#beans-factory-extension-factorybean
[2].FactoryBean的使用