spring 源码简单分析之FactoryBean

FactoryBean的使用

     在一般的情况下,spring通过反射机制利用bean的class属性指定实现类来实例化bean。在某些情况下,实例化bean比较复杂,按照传统的方式,则需要在<bean>中提供大量的配置信息,配置方式的灵活性受到限制,这时采用编码的方式可能得到简单的方案。spring为此提供了一个org.springframework.beans.factory.FactoryBean的工厂类接口,用户就可以通过实现该接口来定制实例化bean的逻辑。

其在spring中占有重要地位。它们隐藏了一些实例化过程中复杂的bean的细节,给上层带来便利。

public interface FactoryBean<T> {

	/**
	返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到spring的容器中单实例缓存池中
	 */
	T getObject() throws Exception;

	/**
	 *返回Factory Bean创建的bean类型
	 */
	Class<?> getObjectType();

	/**
	 返回由FactoryBean创建的bean实例的作用域是singleton还是prototype
	 */
	boolean isSingleton();

例如以下代码示例:

package springSourseAnalyes;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;


public class MyFactoryBeanTest implements FactoryBean<BeanA>,InitializingBean,BeanPostProcessor{
	
	private String userInfo;
	
	private BeanA a;
	
	public void setUserInfo(String userInfo) {
		this.userInfo = userInfo;
	}

	@Override
	public BeanA getObject() throws Exception {
		String[] split = userInfo.split(";");
		a.setNameString(split[0]);
		a.setAge(Integer.parseInt(split[1]));
		return a;
	}

	@Override
	public Class<?> getObjectType() {
		// TODO Auto-generated method stub
		return BeanA.class;
	}

	/**
	 * 如果是单例,则放到spring容器的单例缓存中
	 */
	@Override
	public boolean isSingleton() {
		return false;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("====调用接口Initialize接口的afterPropertiesSet===实例化bean=========");
		a = new BeanA();
		//如果afterPropertiesSet方法抛出异常,则xml配置的init-method也不会执行
//		throw new Exception();
	}
	
	public String getUserInfo() {
		return userInfo;
	}

	void init(){
		System.out.println("调用xml配置的init-method属性。。。。。。");
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		System.out.println("开始调用postProcessBeforeInitialization。。。。"+bean+":"+beanName);
		return null;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
		System.out.println("开始调用postProcessAfterInitialization。。。。"+bean+":"+beanName);
		return bean;
	}
}

xml配置:

<bean id="myBeanFactory" class="springSourseAnalyes.MyFactoryBeanTest" init-method="init" lazy-init="true">
		<property name="userInfo"  value="fack;20"/>
	</bean>

调用:

BeanA bbA = (BeanA) bean.getBean("myBeanFactory");
		System.out.println("name:"+bbA.getNameString() + ",age :"+bbA.getAge());
		
		BeanA aTestA = (BeanA) bean.getBean("a");
		System.out.println(aTestA);
//      如果希望获取MyFactoryBeanTest的实例,则需要在getBean(beanName)方法时在beanName前显
//      示的加上“&”前缀,例如 bean.getBean("&myBeanFactory");
//		在name 前加&,则获取的是MyFactoryBeanTest实例
		MyFactoryBeanTest myFactoryBeanTest = (MyFactoryBeanTest)     
        bean.getBean("&myBeanFactory");
		System.out.println("MyFactoryBeanTest对象:"+":"+myFactoryBeanTest.getUserInfo());

注意: 如果希望获取MyFactoryBeanTest的实例,则需要在getBean(beanName)方法时在beanName前显
      示的加上“&”前缀,例如 bean.getBean("&myBeanFactory");

在AbstractBeanFactory类中。

protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {

		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			checkMergedBeanDefinition(mbd, beanName, args);

			// Guarantee initialization of beans that the current bean depends on.
			String[] dependsOn = mbd.getDependsOn();
			if (dependsOn != null) {
				for (String dependsOnBean : dependsOn) {
					getBean(dependsOnBean);
					registerDependentBean(dependsOnBean, beanName);
				}
			}

			// Create bean instance.
			if (mbd.isSingleton()) {
				sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
					public Object getObject() throws BeansException {
						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;
						}
					}
				});
				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			}

			else if (mbd.isPrototype()) {
				// It's a prototype -> create a new instance.
				Object prototypeInstance = null;
				try {
					beforePrototypeCreation(beanName);
					prototypeInstance = createBean(beanName, mbd, args);
				}
				finally {
					afterPrototypeCreation(beanName);
				}
				bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
			}

			else {
				String scopeName = mbd.getScope();
				final Scope scope = this.scopes.get(scopeName);
				if (scope == null) {
					throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
				}
				try {
					Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
						public Object getObject() throws BeansException {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						}
					});
					bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
				}
				catch (IllegalStateException ex) {
					throw new BeanCreationException(beanName,
							"Scope '" + scopeName + "' is not active for the current thread; " +
							"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
							ex);
				}
			}
		}

		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
			try {
				return getTypeConverter().convertIfNecessary(bean, requiredType);
			}
			catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type [" +
							ClassUtils.getQualifiedName(requiredType) + "]", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

在获取到bean之后,会调用频率最高的方法:getObjectForBeanInstance()。无论是从缓存中获取beanh还是根据不同的scope策略来加载bean,都会调用此方法。其方法j就是用于检测当前bean是否是FactoryBean类型的bean,如果是,那么需要调用该bean对应的FactoryBean实例中的getObject()作为返回值。

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

		// 如果指定的name是工厂相关(以&为前缀)且beanInstance又不是FactoryBean类型则验证不通
        //过
		if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
		}

		// 现在我们有了bean的实例,这个实例k可能会是正常的bean,或者是FactoryBean
		// 如果是FactoryBean我们s使用它创建实例,但是如果用户想要直接获取工厂实例还不是工厂的
        //getObeact方法对应的s实例,那么传入的name应该加入前缀"&"
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}
        //加载fACTORYBean

		Object object = null;
		if (mbd == null) {
            //尝试从缓存中加载bean
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// 到这里已经明确知道beanInstance一定是FactoryBean类型
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// containsBeanDefinition检测beanDefinitionMap中也就是在所有已经加载的类中检测是
            //否定义beanName
			if (mbd == null && containsBeanDefinition(beanName)) {
            //将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,如果指定
            //BeanName是子Bean的话 同时会合并父类的相关属性
				mbd = getMergedLocalBeanDefinition(beanName);
			}
            //是否是用户定义的而不是应用程序本身定义的
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

从上面的代码逻辑看,只是些功能的性的判断,没有核心的东西,并且委托给了getObectFromFactoryBean。

上面的代码主要的工作:

  1. 对FactoryBean正确性的验证
  2. 对非FactoryBean不做任何处理
  3. 对bean进行转换
  4. 将从Factory中解析bean的工作委托给getObjectFromFactoryBean
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) {
					object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
					this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
				}
				return (object != NULL_OBJECT ? object : null);
			}
		}
		else {
			return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
		}
	}

在这个代码只是做了一件事:j就是返回bean,如果是单例的,那就必须要保证q全局唯一,也因为是单例的,所以不必重复创建,k可以使用缓存来提高性能,也就是已经加载的就要记录下来以便于下次复用。否则就直接获取。

private Object doGetObjectFromFactoryBean(
			final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
			throws BeanCreationException {

		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
						public Object run() throws Exception {
								return factory.getObject();
							}
						}, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
                //直接调用getObject获取bean
				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 && isSingletonCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(
					beanName, "FactoryBean which is currently in creation returned null from getObject");
		}

		if (object != null && shouldPostProcess) {
			try {
                //调用ObjectFactory的后处理器
				object = postProcessObjectFromFactoryBean(object, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
			}
		}

		return object;
	}

这个方法才是真正调用了,factorybean的方法getObject来返回,但是并没有直接返回,而是又做了些后处理的操作。

spring在获取bean的规则中有这么一条:尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理,在实际开发过程中大可以针对此特性来设计自己的业务逻辑。

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值