FactoryBean接口中三个方法:
T getObject() throws Exception; 指定返回的实例
Class<?> getObjectType(); 指定返回的实例类型
default boolean isSingleton() {return true; } 指定创建类型,默认单例
public class FactoryBeanBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class MyFactoryBean implements FactoryBean<FactoryBeanBean> {
@Override
public FactoryBeanBean getObject() throws Exception {
FactoryBeanBean factoryBeanBean = new FactoryBeanBean();
factoryBeanBean.setName("username");
return factoryBeanBean;
}
@Override
public Class<?> getObjectType() {
return FactoryBeanBean.class;
}
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
public class FactoryBeanTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("creation.method.factory.bean.xml");
Object myFactoryBean = classPathXmlApplicationContext.getBean("&myFactoryBean");
FactoryBeanBean factoryBeanBean = (FactoryBeanBean) classPathXmlApplicationContext.getBean("myFactoryBean");
FactoryBeanBean factoryBeanBean2 = (FactoryBeanBean) classPathXmlApplicationContext.getBean("myFactoryBean");
System.out.println(factoryBeanBean.getName());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="myFactoryBean" class="com.self.bean.initialization.creation.method.factory.bean.MyFactoryBean"/>
</beans>
首先按spring启动流程创建xml定义的myFactoryBean, 这部分创建流程和spring创建普通bean流程一样。
看下getBean流程:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
---------------11111------------------
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
---------------11111------------------
// 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.
---------------2222------------------
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
---------------2222------------------
---------------3333------------------
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
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;
---------------3333------------------
}
这部分可分为三个部分
1、获取factoryBean
对应Test文件里的代码:
Object myFactoryBean = classPathXmlApplicationContext.getBean("&myFactoryBean");
2、获取普通bean,也就是所有单例非factoryBean的从这里获取。
3、获取factoryBean中的实际Bean
对应Test文件里的代码:
FactoryBeanBean factoryBeanBean = (FactoryBeanBean) classPathXmlApplicationContext.getBean(“myFactoryBean”);