Spring源码分析之FactoryBean原理及使用

前言

FactoryBean可以看做一个工厂Bean,它的getObject()方法可以生产另外一个Bean,且生产的Bean也由Spring管理。

简单使用

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

public class TestFactoryBean {

  public static void main(String[] args) {
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder
        .genericBeanDefinition(UserServiceFactoryBean.class);
    definitionBuilder.addPropertyValue("username", "lisi");
    beanFactory.registerBeanDefinition("userService", definitionBuilder.getBeanDefinition());
    UserService userService = (UserService) beanFactory
        .getBean("userService");
    System.out.println(userService.getUsername());//lisi
    UserServiceFactoryBean userServiceFactoryBean = (UserServiceFactoryBean) beanFactory
        .getBean("&userService");
    System.out.println(userServiceFactoryBean.username);//lisi
  }

  public static class UserServiceFactoryBean implements FactoryBean<UserService> {

    private String username;

    public void setUsername(String username) {
      this.username = username;
    }

    @Override
    public UserService getObject() {
      UserService userService = new UserService();
      userService.setUsername(username);
      return userService;
    }

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

  @Setter
  @Getter
  public static class UserService {

    private String username;
  }

}

我们定义一个UserServiceFactoryBean,用来生产UserService,将其注册到BeanFactory中,如果使用UserService对象,使用userService的Bean名称,
如果想要获取原来的UserServiceFactoryBean对象,需要使用&userService的Bean名称,&这个前缀是Spring规定的,可以查看BeanFactory的FACTORY_BEAN_PREFIX常量。

原理分析

关于Bean大概的创建过程,Spring源码分析之Bean生命周期 已经介绍的差不多了,
这次在它的基础上我们来分析Spring对FactoryBean的处理。先进入AbstractBeanFactory的doGetBean()方法。

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
                //处理FactoryBean类型的Bean名称,去除FactoryBean的前缀,如果name为&userService,处理之后为userService
                //其实这一步还会处理Bean别名,如果userService的别名为userServiceAlias,name为userServiceAlias,处理之后为原来的userService(根据别名查找到原来的Bean名称)
		final String beanName = transformedBeanName(name);
		Object bean;
		//查看是否已经创建过(从单例池中查询)
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
                        //处理FactoryBean相关,核心方法
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		else {
			try {
				//创建单例Bean
				if (mbd.isSingleton()) {
                                        //创建完成之后会将Bean放到单例池中,下次直接从池中取就可以了
					sharedInstance = getSingleton(beanName, () -> {
						try {
                                                        //真正创建Bean的地方,这一步是创建的FactoryBean自己,这里就是UserServiceFactoryBean对象。
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							 //销毁Bean
							destroySingleton(beanName);
							throw ex;
						}
					});
                                        //处理FactoryBean相关
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
			}
		}
		return (T) bean;
	}

创建FactoryBean工厂生产的对象核心方法为getObjectForBeanInstance(),继续跟进去,注意AbstractAutowireCapableBeanFactory(AbstractBeanFactory的子类)重写了此方法

@Override
protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
                //处理依赖相关,暂时不管
		String currentlyCreatedBean = this.currentlyCreatedBean.get();
		if (currentlyCreatedBean != null) {
			registerDependentBean(beanName, currentlyCreatedBean);
		}
                //这里又进入了父类的getObjectForBeanInstance()方法,核心方法
		return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
	}

进入父类(AbstractBeanFactory)的getObjectForBeanInstance()方法

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		//判断是否以前缀&开头,如果以&开头,说明获取的Bean是FactoryBean自身对象,beanInstance此时就是FactoryBean类型,原因看总结
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

		//此时beanInstance一定就是FactoryBean类型
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd != null) {
                        //mbd不为null说明此时是第一次创建FactoryBean生产的对象
			mbd.isFactoryBean = true;
		}
		else {
                        //直接从缓存中取
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			//调用FactoryBean的getObject()方法生产对象
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

继续getObjectFromFactoryBean()方法,真正生产另一个Bean对象的地方

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);
					//处理循环引用相关,所以又get()一次,暂时不管
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							//此方法为AbstractAutowireCapableBeanFactory重写,应用BeanPostProcessor的postProcessAfterInitialization()方法
                                                        //在Bean初始化之后做一些事情
							try {
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
						}
						if (containsSingleton(beanName)) {
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
                        //处理非单例情况,每次都创建一个,不保存到factoryBeanObjectCache中
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
			}
			return object;
		}
	}

从上面一个方法可以看到,对于FactoryBean生产的另一个Bean(这里就是UserService),是不走默认的初始化流程的(属性装配,Aware钩子回调,initMethod方法回调),
不会处理@Autowired,@Value注解。

原理总结

正常的Bean实例(非FactoryBean生产)是存储在DefaultSingletonBeanRegistry的singletonObjects属性中(IOC容器的底层实现),
而FactoryBean生产的对象是存储在FactoryBeanRegistrySupport的factoryBeanObjectCache属性中,这两个类都是DefaultListableBeanFactory的父类。
以上述例子来说,Bean名称&userService对应的Bean类型为UserServiceFactoryBean,存储在singletonObjects(单例池,是一个Map)中(会处理Bean名称,去除&前缀,所以这里存储的key也是userService),
Bean名称userService对应的Bean类型为UserService,存储在factoryBeanObjectCache中。

  • getBean("userService")的流程: 查询singletonObjects得到Bean实例(如果没有就创建并保存到singletonObjects中),请求的Bean名称没有以&开头,且对象类型为FactoryBean,调用FactoryBean的getObject()生成对象,并保持到factoryBeanObjectCache缓存中,后续直接从缓存中取。
  • getBean("&userService")的流程: 根据处理后的name(去除&前缀)查询singletonObjects得到Bean实例(如果没有就创建并保存到singletonObjects中),请求的Bean名称以&开头,直接返回对象。

使用场景

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

public class TestFactoryBean2 {

  public static void main(String[] args) {
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    //注册UserMapper
    BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder
        .genericBeanDefinition(MapperFactoryBean.class);
    definitionBuilder.addPropertyValue("mapperInterface", UserMapper.class);
    beanFactory.registerBeanDefinition("userMapper", definitionBuilder.getBeanDefinition());
    //注册AddressMapper
    definitionBuilder = BeanDefinitionBuilder
        .genericBeanDefinition(MapperFactoryBean.class);
    definitionBuilder.addPropertyValue("mapperInterface", AddressMapper.class);
    beanFactory.registerBeanDefinition("addressMapper", definitionBuilder.getBeanDefinition());
    UserMapper userMapper = (UserMapper) beanFactory.getBean("userMapper");
    System.out.println(userMapper.getCount());
    AddressMapper addressMapper = (AddressMapper) beanFactory.getBean("addressMapper");
    System.out.println(addressMapper.getCount());

  }

  public static class MapperFactoryBean<T> implements FactoryBean<T> {

    private Class<T> mapperInterface;

    public void setMapperInterface(Class<T> mapperInterface) {
      this.mapperInterface = mapperInterface;
    }

    @Override
    public T getObject() {
      //使用JDK动态代理创建对象
      return (T) Proxy
          .newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface},
              new MapperProxy());
    }

    @Override
    public Class<?> getObjectType() {
      return mapperInterface;
    }
  }

  public static class MapperProxy implements InvocationHandler {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      System.out.println(method.getName() + " invoked");
      return null;
    }
  }

  interface UserMapper {

    Integer getCount();
  }

  interface AddressMapper {

    Integer getCount();
  }

}

定义一个FactoryBean,可以根据不同的接口类型创建不同的实现,Mybatis的MapperFactoryBean和SpringDataJPA的JpaRepositoryFactoryBean就是这样实现的,
所以FactoryBean适用于创建一类相似且统一的Bean对象,且创建过程比较复杂。FactoryBean作为一个工厂Bean,如果只是创建一个或者很少的对象,确实没有使用的必要,
只有需要创建大量的对象的情况(可以类比现实中的工厂),才能体现出优势。

posted @ 2022-05-07 20:11  strongmore  阅读(281)  评论(0编辑  收藏  举报