美文网首页Java架构技术进阶spring framework
源码分析之 FactoryBean接口不为人知的秘密

源码分析之 FactoryBean接口不为人知的秘密

作者: 架构小白菜 | 来源:发表于2021-06-25 15:41 被阅读0次

    FactoryBean接口在spring中是一个非常好用且容易被人忽略的接口。OK借助这个机会我们把它的秘密扒出来,让它落体出镜好吧。

    首先贴一个代码:

    import org.springframework.beans.factory.FactoryBean;
    public class FactoryBeanTest implements FactoryBean {
     private UserService userService;
     public UserService getUserService() {
     return userService;
     }
     public void setUserService(UserService userService) {
     this.userService = userService;
     }
     @Override
     public Object getObject() throws Exception {
     return new UserServiceImpl();
     }
     @Override
     public Class<?> getObjectType() {
     return userService.getClass();
     }
     @Override
     public boolean isSingleton() {
     return true;
     }
    }
    
    

    这个代码很简单,弄一个类实现了FactoryBean接口,而接口中有三个必须实现的方法:

    getObject、getObjectType、isSingleton

    在getObject中我们new UserServiceImpl();实例。然后我们在配置文件中是这样实例化FactoryBeanTest 类的:

     <bean id="factoryBeanTest" class="com.xiangxueedu.carry.factoryBean.FactoryBeanTest">
    </bean>
    
    

    那么我们通过spring的上下文根据id,id="factoryBeanTest"获取FactoryBeanTest的实例。

    ApplicationContext applicationContext = ApplicationContextAwareTest.getApplicationContext();
    UserServiceImpl userService = (UserServiceImpl)applicationContext.getBean("factoryBeanTest");
    System.out.println(userService);
    
    

    OK,我们看看打印的对象是什么:

    com.xiangxueedu.carry.factoryBean.UserServiceImpl@5038d0b5
    
    

    从结果我们可以看到,打印出来的是FactoryBeanTest类中的getObject方法的返回对象。这是实现了FactoryBean接口的通常用法。根据Id获取到的是getObject的方法值对象。

    OK,有的时候我们需要根据Id获取到类本身怎么办,

    比如:<bean id="factoryBeanTest" class="com.xiangxueedu.carry.factoryBean.FactoryBeanTest"> </bean>

    要根据id=“factoryBeanTest”,获取到FactoryBeanTest这个类本身,怎么呢??

    有办法,我们只要用上下文对象的getBean方法中加一个“&”就行了。如下:

    ApplicationContext applicationContext = ApplicationContextAwareTest.getApplicationContext();
    FactoryBeanTest factoryBeanTest = (FactoryBeanTest)applicationContext.getBean("&factoryBeanTest");
    System.out.println(factoryBeanTest);
    
    

    打印结果如下:

    com.xiangxueedu.carry.factoryBean.FactoryBeanTest@5038d0b5
    
    

    我们用“&factoryBeanTest”的方式成功的拿到了FactoryBeanTest类的实例。

    根据两种情况我们分析一下源码:

    **

    1、没有“&”号为什么根据Id获取到的是getObject方法的返回对象?

    image

    其实加“&”和不加“&”就是影响了一个if的判断,导致了代码往不往下执行。

    image

    我们进去看看BeanFactoryUtils.isFactoryDereference(name),第一个条件!(beanInstance instanceof FactoryBean)如果是factorybean类型的bean正在实例化,那么肯定是false的。

    String FACTORY_BEAN_PREFIX = “&”;

    这里就判断了id中有没有存在“&”符号,如果有则返回true,返回true就直接return beanInstance;把实例本身返回了,而实例本身就是例子中的FactoryBeanTest。

    如果id中没有“&”,则返回false,那么代码往下执行。

    image

    会执行到这个方法。

    image

    这里就调到了getObject方法,所以拿到的对象就是getObject方法返回的对象。OK。

    从分析源码我们可以看到,就是一个“&”符号控制了代码的流转,有“&”拿到的是类本身实例,没有“&”拿到的getObject返回实例。

    相关文章

      网友评论

        本文标题:源码分析之 FactoryBean接口不为人知的秘密

        本文链接:https://www.haomeiwen.com/subject/jgroyltx.html