Spring FactoryBean源码浅析
在Spring BeanFactory容器中管理两种bean 1.标准Java Bean 2,另一种是工厂Bean, 即实现了FactoryBean接口的bean 它不是一个简单的Bean 而是一个生产或修饰对象生成的工厂Bean在向Spring容器获得bean时 对于标准的java Bean 返回的是类自身的实例 而FactoryBean 其返回的对象不一定是自身
在Spring BeanFactory容器中管理两种bean
1.标准Java Bean
2,另一种是工厂Bean, 即实现了FactoryBean接口的bean 它不是一个简单的Bean 而是一个生产或修饰对象生成的工厂Bean
在向Spring容器获得bean时 对于标准的java Bean 返回的是类自身的实例
而FactoryBean 其返回的对象不一定是自身类的一个实例,返回的是该工厂Bean的getObject方法所返回的对象
一个简单的例子
public class SayHelloFactoryBeanImpl implements FactoryBean {
/**
* 返回该工厂生成的bean
*/
public Object getObject() throws Exception {
return new ChinaSayHelloServiceImpl();
}
/**
* getObject返回对象对应的Class
*/
public Class getObjectType() {
return ChinaSayHelloServiceImpl.class;
}
/**
* getObject返回的对象 是否是一个单例
*/
public boolean isSingleton() {
return false;
}
}
配置文件
<bean id="sayHelloFactoryBean" class="com.xx.service.impl.SayHelloFactoryBeanImpl" />
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext-server.xml"}, true);
//bean的 getObject方法 返回的对象
Object object = context.getBean("sayHelloFactoryBean");
System.out.println(object);
控制台输出
com.xx.service.impl.ChinaSayHelloServiceImpl@1f66cff
容器返回的是 bean getObject方法返回对象 而不是SayHelloFactoryBeanImpl自身的实例 当然可以用“&”符号转义 获得FactoryBean的自身实例
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext-server.xml"}, true);
//可以用转义符"&"来获得FactoryBean本身实例
System.out.println(context.getBean("&sayHelloFactoryBean"));
控制台输出
com.xx.service.impl.SayHelloFactoryBeanImpl@75e4fc
下面看看FactoryBean是怎么实现的
Spring FactoryBean接口定义
public interface FactoryBean {
Object getObject() throws Exception;
Class getObjectType();
boolean isSingleton();
}
bean的实例化 是在AbstractBeanFactory getBean方法发生的
public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {
return doGetBean(name, requiredType, args, false);
}
protected Object doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
// bean name处理 如果是以"&"开头 截取掉
final String beanName = transformedBeanName(name);
Object bean = null;
//单例的bean 只实例化一次 第一次实例化后会放到一个Map中 即singletonObjects map集合中 下次使用的时候直接拿
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// FactoryBean 相关处理 在此方法发生
//name 调用getBean时传入的参数
//beanName 截取"&"后的name
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
...略
}
return bean;
}
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// 如果不是FactoryBean的相关调用 结束处理
//isFactoryDereference 方法判断name 是不是以"&"开始 如果以"&"开始 返回true
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
//bean的定义为null
if (mbd == null) {
//缓存集合factoryBeanObjectCache中包含 当前bean getObject方法返回的实例 不需要在调用 直接返回
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
FactoryBean factory = (FactoryBean) beanInstance;
//containsBeanDefinition方法-> bean的定义map beanDefinitionMap集合中 是否包含该bean的定义
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// FactoryBean getObject触发 并缓存到factoryBeanObjectCache集合中
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
//当前的factoryBean是否单例 并且 缓存singletonObjects‘Map中包含FactoryBean的自身实例
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
// factoryBeanObjectCache 缓存的是 getObject返回的对象
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//getObject方法调用
object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
//缓存 getObject方法返回的实例对象
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
return (object != NULL_OBJECT ? object : null);
}
}
else {
//getObject方法调用
return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
}
}
private Object doGetObjectFromFactoryBean(
final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
throws BeanCreationException {
AccessControlContext acc = AccessController.getContext();
return AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
Object object;
try {
// getObject方法调用
object = factory.getObject();
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
}
}
return object;
}
}, acc);
}
当一个受Spring容器管理的bean 如果实现了FactoryBean接口 在bean实例化(getBean)阶段 Spring会调用该bean的getObejct方法 返回的不一定是自身的实例
Spring 框架中有很多FactoryBean 例如RmiProxyFactoryBean, SqlMapClientFactoryBean. LocalSessionFactoryBean等都是通过FactoryBean getObject方法驱动起来的.对bean的生产 修饰做了很好的封装。
更多推荐
所有评论(0)