一、代码实例
在我们分析spring的IOC源码的时候,发现除了配置标准的bean,并且通过getBean(beanName)的方法获取到一个bean的实例外,似乎还有这不少其他获取的方法,例如在第四节,我们发现得到bean实例后,在第26节,会判断是否继承了FactoryBean,然后调用它的方法获取真实的bean,在配置文件中我们发现一个factory-bean方法,这些都说明,我们应该可以使用一个beanFactory获取一个bean,此节重点讨论这部分的实现。
代码如下:
1、car类
package com.zjl.factorybean; public class Car { public Car(String name) { this.name=name; } String name; public void run(){ System.out.println(this.name+" is running"); } }
2、person类
package com.zjl.factorybean; public class Person { public Person(String name) { this.name=name; } public String name; public int age; public Car car; public void sayHello(){ System.out.println(this.name+" say hello"); } public Car createCar(){ return new Car("奥迪"); } }
3、用来获取person的FactoryBean,必须继承FactoryBean接口
package com.zjl.factorybean; import org.springframework.beans.factory.FactoryBean; public class PersonFactory implements FactoryBean<Person> { String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public Person getObject() throws Exception { return new Person(name); } @Override public Class<Person> getObjectType() { return Person.class; } @Override public boolean isSingleton() { return true; } }
4、配置文件
<bean id="personFactory" class="com.zjl.factorybean.PersonFactory"> <property name="name" value="zhangsan"></property> </bean> <bean id="car" factory-method="createCar" factory-bean="personFactory"></bean>
5、测试类
package com.zjl.factorybean; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ClassPathResource; public class Test { public static void main(String[] args) throws Exception { DefaultListableBeanFactory beanFacory=new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(beanFacory); reader.loadBeanDefinitions(new ClassPathResource("factorybean.xml")); Person person=(Person)beanFacory.getBean("personFactory"); person.sayHello(); Person person2=(Person)beanFacory.getBean("personFactory"); System.out.println("person==person2 is "+(person==person2)); Car car=(Car)beanFacory.getBean("car"); car.run(); Car car2=(Car)beanFacory.getBean("car"); System.out.println("car==car2 is "+(car==car2)); } }
6、测试结果
zhangsan say hello person==person2 is true 奥迪 is running car==car2 is true
7、结论
我们可以看到:
a)通过getBean(beanName)方法获取到的直接就是Person的实例,而不是BeanFactory或者PersonFactory的实例。
b)每次获取到的Person实例都是同一个,根据接口中的方法isSingleton方法,猜测于此有关
c)bean的id为car,并没有配置我们常见的class配置,他应该是执行了Person的createCar方法
d)car也遵循单例模式
二、FactoryBean代码解析
1、通过我们对bean的加载过程,发现所有的配置无论是spring默认bean的 配置,还是客户自定义的配置均无差别的被解析后存放在beanDefinitionMap中,所以解析配置文件过程不再重复。
2、Person person=(Person)beanFacory.getBean("personFactory");生成bean过程与第四部分重复的跳过
3、来到bean生成实例后的地方
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd)
4、进入方法,判断如果是bean不是FactoryBean的实例且beanName是&开头,抛出错误。是FactoryBean的实例,且以&开头,则直接返回实例。
将实例转化为FactoryBean的实例,并且调用getObjectFromFactoryBean(factory, beanName, !synthetic)方法
注:也就是我们要获得定义的通过personFactory返回PersonFactory的实例,可以使用beanFacory.getBean("&personFactory")进行获取,然后调用getObject也可以返回Person的实例,不过这个需要自己控制单例模式
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { // Don't let calling code try to dereference the factory if the bean isn't a factory. if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); }//bean不是FactoryBean的实例且beanName是&开头,报错 // Now we have the bean instance, which may be a normal bean or a FactoryBean. // If it's a FactoryBean, we use it to create a bean instance, unless the // caller actually wants a reference to the factory.
//bean是FactoryBean的实例,且beanName以&开头,返回实例
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } Object object = null; if (mbd == null) { 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; }
5、调用factory实例的isSingleton方法和containsSingleton(beanName),判断是否是单例模式,单例模式的话,从factoryBeanObjectCache中尝试读取,否则直接生成。
注:我们可以看到,通过FactoryBean的对象是否是单例模式取决于bean定义的范围和方法isSingleton同时为单例才可以
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); // Only post-process and store if not put there already during getObject() call above // (e.g. because of circular reference processing triggered by custom getBean calls) Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { if (object != null && shouldPostProcess) { try { object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", ex); } } this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT)); } } return (object != NULL_OBJECT ? object : null); } } else { Object object = doGetObjectFromFactoryBean(factory, beanName); if (object != null && shouldPostProcess) { try { object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex); } } return object; } }
6、doGetObjectFromFactoryBean中调用getObject方法,返回实例
7、调用bean后处理postProcessObjectFromFactoryBean并放入缓存factoryBeanObjectCache
到此,我们已经获取到了真正的bean,并且也知道了怎么获取原来定义的FactoryBean的实例,但是,似乎少了一个方法,那就说FactoryBean中的getObjectType,我们需要回头去找哪里漏掉了
我翻遍了源代码,并没有找到此方法调用的地方,事实上通过改动
@Override public Class<Car> getObjectType() { return Car.class; }
或者
@Override public Class<Person> getObjectType() { return null; }
都不会影响代码执行结果的正确性,那么我们猜想,是否仅仅是一个预留,并无实际用处,或者客户自定义使用方法。
三、FactoryBean实例
在上一步查找源代码过程中,我们有了新的发现,spring自定义了抽象类AbstractFactoryBean和大量他的子类,包括我们常见的list,map,set,object等,我们也来研究下
1、首先是他的继承关系
public abstract class AbstractFactoryBean<T> implements FactoryBean<T>, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
我们看到继承了几个熟悉的接口,包括FactoryBean和InitializingBean,还有几个BeanClassLoaderAware, BeanFactoryAware, DisposableBean,这些接口分别是:
FactoryBean:通过getObjectBean生成bean实例
InitializingBean:在实例化后执行afterPropertiesSet方法
以上我们比较熟悉,其余三个接口简单了解下
BeanClassLoaderAware:注入classLoad
BeanFactoryAware:注入一个BeanFactory
DisposableBean:销毁bean默认调用destroy方法
我们这里重点关注FactoryBean的三个接口实现:
2、是否单例,通过外部注入
public boolean isSingleton() { return this.singleton; }
3、getObject方法,如果是单例且已经创建,返回单例模式,未创建调用getEarlySingletonInstance方法,不是单例模式,调用createInstance方法
@Override public final T getObject() throws Exception { if (isSingleton()) { return (this.initialized ? this.singletonInstance : getEarlySingletonInstance()); } else { return createInstance(); } }
4、getEarlySingletonInstance方法,通过第5步判断,是否为接口,如果是通过动态代理,创建对象
private T getEarlySingletonInstance() throws Exception { Class<?>[] ifcs = getEarlySingletonInterfaces(); if (ifcs == null) { throw new FactoryBeanNotInitializedException( getClass().getName() + " does not support circular references"); } if (this.earlySingletonInstance == null) { this.earlySingletonInstance = (T) Proxy.newProxyInstance( this.beanClassLoader, ifcs, new EarlySingletonInvocationHandler()); } return this.earlySingletonInstance; }
5、此处调用getObjectType,判断是否为空或者是否为接口,如果是,返回,否则为空
protected Class<?>[] getEarlySingletonInterfaces() { Class<?> type = getObjectType(); return (type != null && type.isInterface() ? new Class<?>[] {type} : null); }
6、动态代理的InvocationHandler 类,似乎什么都没干,存疑
private class EarlySingletonInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (ReflectionUtils.isEqualsMethod(method)) { // Only consider equal when proxies are identical. return (proxy == args[0]); } else if (ReflectionUtils.isHashCodeMethod(method)) { // Use hashCode of reference proxy. return System.identityHashCode(proxy); } else if (!initialized && ReflectionUtils.isToStringMethod(method)) { return "Early singleton proxy for interfaces " + ObjectUtils.nullSafeToString(getEarlySingletonInterfaces()); } try { return method.invoke(getSingletonInstance(), args); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } }
分析到这里,似乎这个类什么都没做,我们具体看个实例类ListFactoryBean,此类注入了以下参数:
a、sourceList是一个list
b、targetListClass是一个Class
c、重写了createInstance(),将sourceList修改后注入
public class ListFactoryBean extends AbstractFactoryBean<List<Object>> { private List<?> sourceList; @SuppressWarnings("rawtypes") private Class<? extends List> targetListClass; /** * Set the source List, typically populated via XML "list" elements. */ public void setSourceList(List<?> sourceList) { this.sourceList = sourceList; } /** * Set the class to use for the target List. Can be populated with a fully * qualified class name when defined in a Spring application context. * <p>Default is a {@code java.util.ArrayList}. * @see java.util.ArrayList */ @SuppressWarnings("rawtypes") public void setTargetListClass(Class<? extends List> targetListClass) { if (targetListClass == null) { throw new IllegalArgumentException("'targetListClass' must not be null"); } if (!List.class.isAssignableFrom(targetListClass)) { throw new IllegalArgumentException("'targetListClass' must implement [java.util.List]"); } this.targetListClass = targetListClass; } @Override @SuppressWarnings("rawtypes") public Class<List> getObjectType() { return List.class; } @Override @SuppressWarnings("unchecked") protected List<Object> createInstance() { if (this.sourceList == null) { throw new IllegalArgumentException("'sourceList' is required"); } List<Object> result = null; if (this.targetListClass != null) { result = BeanUtils.instantiateClass(this.targetListClass); } else { result = new ArrayList<Object>(this.sourceList.size()); } Class<?> valueType = null; if (this.targetListClass != null) { valueType = GenericCollectionTypeResolver.getCollectionType(this.targetListClass); } if (valueType != null) { TypeConverter converter = getBeanTypeConverter(); for (Object elem : this.sourceList) { result.add(converter.convertIfNecessary(elem, valueType)); } } else { result.addAll(this.sourceList); } return result; } }