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


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

    1. public interface WebService {
    2. void service();
    3. }
    4. public class DefaultWebService implements WebService {
    5. private String serviceName;
    6. public DefaultWebService(String serviceName) {
    7. this.serviceName = serviceName;
    8. }
    9. @Override
    10. public void service() {
    11. System.out.println(serviceName + ": current support service for you....");
    12. }
    13. }
    14. public class WebServiceWrapper implements WebService {
    15. private WebService webService;
    16. public WebServiceWrapper(WebService webService) {
    17. this.webService = webService;
    18. }
    19. @Override
    20. public void service() {
    21. System.out.println("befor service, we need do something....");
    22. webService.service();
    23. }
    24. }

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

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

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

    1. @Component
    2. public class WebServiceFactoryBean implements FactoryBean {
    3. @Override
    4. public boolean isSingleton() {
    5. return true;
    6. }
    7. @Override
    8. public Object getObject() throws Exception {
    9. return this.createWebService();
    10. }
    11. @Override
    12. public Class getObjectType() {
    13. return WebService.class;
    14. }
    15. private Object createWebService() {
    16. DefaultWebService webService = new DefaultWebService("Backend Service");
    17. // create a proxy
    18. WebServiceWrapper webServiceWrapper = new WebServiceWrapper(webService);
    19. return webServiceWrapper;
    20. }
    21. }
    1. @Component
    2. public class WebServiceFactoryBean implements FactoryBean {
    3. @Override
    4. public boolean isSingleton() {
    5. return true;
    6. }
    7. @Override
    8. public Object getObject() throws Exception {
    9. return this.createWebService();
    10. }
    11. @Override
    12. public Class getObjectType() {
    13. return WebService.class;
    14. }
    15. private Object createWebService() {
    16. DefaultWebService webService = new DefaultWebService("Backend Service");
    17. // create a proxy
    18. WebServiceWrapper webServiceWrapper = new WebServiceWrapper(webService);
    19. return webServiceWrapper;
    20. }
    21. }

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

    1. @RestController
    2. public class TestController {
    3. @Autowired
    4. private WebService webService;
    5. @GetMapping(value = "webService")
    6. public void webService() {
    7. webService.service();
    8. }
    9. }

    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的实例化过程:

    1. public void preInstantiateSingletons() throws BeansException {
    2. // Trigger initialization of all non-lazy singleton beans...
    3. for (String beanName : beanNames) {
    4. RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    5. if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    6. if (isFactoryBean(beanName)) {
    7. Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
    8. }
    9. else {
    10. getBean(beanName);
    11. }
    12. }
    13. }
    14. }

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

    1. protected T doGetBean(
    2. String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly)
    3. throws BeansException {
    4. // Create bean instance.
    5. if (mbd.isSingleton()) {
    6. sharedInstance = getSingleton(beanName, () -> {
    7. try {
    8. return createBean(beanName, mbd, args);
    9. }
    10. catch (BeansException ex) {
    11. // Explicitly remove instance from singleton cache: It might have been put there
    12. // eagerly by the creation process, to allow for circular reference resolution.
    13. // Also remove any beans that received a temporary reference to the bean.
    14. destroySingleton(beanName);
    15. throw ex;
    16. }
    17. });
    18. beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    19. }
    20. }

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

    1. /**
    2. 获取给定bean实例的对象,可以是bean实例本身,也可以是FactoryBean所创建的对象。
    3. */
    4. protected Object getObjectForBeanInstance(
    5. Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    6. // 判断beanName是否以FactoryBean "&"特殊前缀开头,如果是以"&"开头
    7. // 说明当前获取的是FactoryBean本身
    8. if (BeanFactoryUtils.isFactoryDereference(name)) {
    9. if (beanInstance instanceof NullBean) {
    10. return beanInstance;
    11. }
    12. if (!(beanInstance instanceof FactoryBean)) {
    13. throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
    14. }
    15. if (mbd != null) {
    16. mbd.isFactoryBean = true;
    17. }
    18. return beanInstance;
    19. }
    20. // 如果该bean不是FactoryBean那么直接返回
    21. if (!(beanInstance instanceof FactoryBean)) {
    22. return beanInstance;
    23. }
    24. // 否则就利用FactoryBean返回该bean
    25. Object object = null;
    26. if (mbd != null) {
    27. mbd.isFactoryBean = true;
    28. }
    29. else {
    30. object = getCachedObjectForFactoryBean(beanName);
    31. }
    32. if (object == null) {
    33. // Return bean instance from factory.
    34. FactoryBean factory = (FactoryBean) beanInstance;
    35. // Caches object obtained from FactoryBean if it is a singleton.
    36. if (mbd == null && containsBeanDefinition(beanName)) {
    37. mbd = getMergedLocalBeanDefinition(beanName);
    38. }
    39. boolean synthetic = (mbd != null && mbd.isSynthetic());
    40. object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    41. }
    42. return object;
    43. }

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

    1. protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
    2. Object object = doGetObjectFromFactoryBean(factory, beanName);
    3. if (shouldPostProcess) {
    4. try {
    5. object = postProcessObjectFromFactoryBean(object, beanName);
    6. }
    7. catch (Throwable ex) {
    8. throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
    9. }
    10. }
    11. return object;
    12. }
    13. private Object doGetObjectFromFactoryBean(FactoryBean factory, String beanName) throws BeanCreationException {
    14. Object object;
    15. try {
    16. if (System.getSecurityManager() != null) {
    17. AccessControlContext acc = getAccessControlContext();
    18. try {
    19. object = AccessController.doPrivileged((PrivilegedExceptionAction) factory::getObject, acc);
    20. }
    21. catch (PrivilegedActionException pae) {
    22. throw pae.getException();
    23. }
    24. }
    25. else {
    26. **object = factory.getObject();**
    27. }
    28. }
    29. catch (FactoryBeanNotInitializedException ex) {
    30. throw new BeanCurrentlyInCreationException(beanName, ex.toString());
    31. }
    32. catch (Throwable ex) {
    33. throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
    34. }
    35. // Do not accept a null value for a FactoryBean that's not fully
    36. // initialized yet: Many FactoryBeans just return null then.
    37. if (object == null) {
    38. if (isSingletonCurrentlyInCreation(beanName)) {
    39. throw new BeanCurrentlyInCreationException(
    40. beanName, "FactoryBean which is currently in creation returned null from getObject");
    41. }
    42. object = new NullBean();
    43. }
    44. return object;
    45. }
    46. 相关阅读:
      LeetCode高频题55. 跳跃游戏
      11/27周总结报告
      spring tx:advice事务配置—— tx:advice中不允许出现属性 ‘transaction-manager‘
      macbook如何通过命令行安装软件
      [附源码]java毕业设计干果在线销售系统设计
      这份神仙面试笔记,简直把所有Java知识面试题写出来了
      由山东高考今日出分记
      java计算机毕业设计高校多媒体设备报修管理系统源码+mysql数据库+系统+lw文档+部署
      Golang | Leetcode Golang题解之第169题多数元素
      OpenHarmony其他工具类—lua
    47. 原文地址:https://blog.csdn.net/qq_38334677/article/details/127838904