Spring-FactoryBean的源码——简略解析(上)

在spring中,如果一个bean的创建过程很复杂,我们可以使用FactoryBean。
比如像下面的情况,我定义一套webService框架。

public interface WebService {
    void service();  
}

public class DefaultWebService implements WebService {
    private String serviceName;

    public DefaultWebService(String serviceName) {
        this.serviceName = serviceName;
    }

    @Override
    public void service() {
        System.out.println(serviceName + ": current support service  for  you....");
    }
}

public class WebServiceWrapper implements WebService {
    private WebService webService;
    public WebServiceWrapper(WebService webService) {
        this.webService = webService;
    }

    @Override
    public void service() {
        System.out.println("befor service, we need do something....");
        webService.service();
    }
}

WebService接口定义服务的标准,DefaultWebService是一个默认实现,WebServiceWrapper的主要作用是在实际服务之前,做一些检查,准备等工作。
因此当我们使用WebService,实际上是希望使用的是WebServiceWrapper。

现在webService框架实现好了,并打包出来了,现在我需要在项目中利用使用spring注解特性去使用。

那该怎么办呢?我可以实现spring提供的FactoryBean接口,就像下面这样:

@Component
public class WebServiceFactoryBean implements FactoryBean {

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public Object getObject() throws Exception {
        return this.createWebService();
    }

    @Override
    public Class<?> getObjectType() {
        return WebService.class;
    }

    private Object createWebService() {
        DefaultWebService webService = new DefaultWebService("Backend Service");
        // create a proxy
        WebServiceWrapper webServiceWrapper = new WebServiceWrapper(webService);
        return webServiceWrapper;
    }
}
@Component
public class WebServiceFactoryBean implements FactoryBean {

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public Object getObject() throws Exception {
        return this.createWebService();
    }

    @Override
    public Class<?> getObjectType() {
        return WebService.class;
    }

    private Object createWebService() {
        DefaultWebService webService = new DefaultWebService("Backend Service");
        // create a proxy
        WebServiceWrapper webServiceWrapper = new WebServiceWrapper(webService);
        return webServiceWrapper;
    }
}

紧接着,就可以利用spring的功能去使用了

@RestController
public class TestController {
    @Autowired
    private WebService webService;

    @GetMapping(value = "webService")
    public void webService() {
        webService.service();
    }
}

http://localhost:8080/webService,控制台会输出:
befor service, we need do something....
Backend Service: current support service for you....

通过输出我们知道,该webService,注入的应该是WebServiceWrapper。
这里的主要疑问是,我们使用@Component托管spring的bean是WebServiceFactoryBean。但是最后在TestController中,WebServiceWrapper的相关信息,只有是怎么被注入的呢?也就是spring是怎么利用FactoryBean来实现特定bean工厂的呢?

spring托管一个bean大概的流程是:
bean信息扫描->实例化->依赖注入->初始化

首先看下bean扫描阶段,在所有扫描出来的BeanDefinition中,没有发现WebServiceWrapper的相关信息,只有WebServiceFactoryBean的相关信息。所以spring不是在扫描阶段解析出WebServiceFactoryBean相关信息的。

再看下WebServiceFactoryBean的实例化过程:

    public void preInstantiateSingletons() throws BeansException {
    // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) {
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);   
                }
                else {
                    getBean(beanName);
                }
            }
        }
    }

这段源码中,有个判断是说如果当前bean是FactoryBean,那么获取该FactoryBean本身时,beanName要加上一个特殊的前缀“&”。由于WebServiceFactoryBean是一个FactoryBean,所以此时调用的是:Object bean = getBean(FACTORY_BEAN_PREFIX + beanName),入参是:&webServiceFactoryBean
spring中getBean会去调用doGetBean():

    protected <T> T doGetBean(
            String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
            throws BeansException {
// Create bean instance.
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
}

先创建一个bean实例,然后通过getObjectForBeanInstance()返回一个实例。
这里疑问是,我明明都创建好了一个实例,我直接返回不就好了吗,为什么还要通过getObjectForBeanInstance()返回呢?下面看看该方法得描述:

/**
获取给定bean实例的对象,可以是bean实例本身,也可以是FactoryBean所创建的对象。
*/
protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

// 判断beanName是否以FactoryBean "&"特殊前缀开头,如果是以"&"开头
// 说明当前获取的是FactoryBean本身
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;
        }
    // 如果该bean不是FactoryBean那么直接返回
    if (!(beanInstance instanceof FactoryBean)) {
            return beanInstance;
        }

    // 否则就利用FactoryBean返回该bean
    Object object = null;
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        else {
            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());
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
}

上面的逻辑也是很清晰了,最后看下

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
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;
}

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
        Object object;
        try {
            if (System.getSecurityManager() != null) {
                AccessControlContext acc = getAccessControlContext();
                try {
                    object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                **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);
        }

        // Do not accept a null value for a FactoryBean that's not fully
        // initialized yet: Many FactoryBeans just return null then.
        if (object == null) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(
                        beanName, "FactoryBean which is currently in creation returned null from getObject");
            }
            object = new NullBean();
        }
        return object;
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快撑死的鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值