源码分析FactoryBean 接口的核心功能是今天的主要内容,下面我们通用一个测试类为入口来详细其核心源码:
1、测试类:
import com.enjoy.jack.bean.Student;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;
@Component
public class FactoryBeanDemo implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new Student();
}
@Override
public Class> getObjectType() {
return Student.class;
}
}
实体:
@Data
public class Student {
private String username = "nandao";
}
2、核心配置:spring.xml
3、运行测试:
@Test
public void test20() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Student student = (Student)applicationContext.getBean("factoryBeanDemo");
System.out.println(student);
FactoryBeanDemo factoryBeanDemo = (FactoryBeanDemo)applicationContext.getBean("&factoryBeanDemo");
System.out.println(factoryBeanDemo);
}
4、结果:
发现没有“&”号为什么根据Id获取到的是getObject方法的返回对象,下面看看源码
5、源码入口:AbstractBeanFactory 类的doGetBean 接口
//从缓存中拿实例
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
//如果缓存里面能拿到实例
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//该方法是FactoryBean接口的调用入口
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
点击 getObjectForBeanInstance(sharedInstance, name, beanName, null);接口
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
//判断对象前面是否家里“&” 符号,如果加了,可能直接返回当前实例的对象;如果没加继续往下走,最终返回getObject里面的对象。
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
//如果实例不是FactoryBean类型的
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
//如果代码能走下来,则说明 beanName不是以&开头,并且beanInstance是FactoryBean类型的
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
//从缓存里面拿FactoryBean类型的实例
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean> factory = (FactoryBean>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//重点看,里面是调用getObject方法,获取对象信息
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
6、点击 BeanFactoryUtils.isFactoryDereference(name)
public static boolean isFactoryDereference(@Nullable String name) {
//判断name里面首个字符串是不是“&”,如果是直接返回true
// String FACTORY_BEAN_PREFIX = "&";
return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}
这里就判断了id中有没有存在“&”符号,如果有则返回true,返回true就直接return beanInstance;把实例本身返回了,而实例本身就是例子中的FactoryBeanDemo
7、点击 getObjectFromFactoryBean(factory, beanName, !synthetic);进入父类FactoryBeanRegistrySupport
protected Object getObjectFromFactoryBean(FactoryBean> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//调用getObject方法,点击进入
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
//把实例缓存到factoryBeanObjectCache map中,这个是单独缓存FactoryBean类型实例的map
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
点击 doGetObjectFromFactoryBean(factory, beanName);方法
private Object doGetObjectFromFactoryBean(FactoryBean> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction
8、此处 factory.getObject(); 就是调到了业务方法,如下:
这里就调到了getObject方法,所以拿到的对象就是getObject方法返回的对象。
总之,从分析源码我们可以看到,就是一个“&”符号控制了代码的流转,有“&”拿到的是类本身实例,没有“&”拿到的getObject返回实例,到此FactoryBean分析完毕。



