问题1:获取lubanFactoryBean里面的bean到底在哪里执行?是容器启动还是getBean的时候
AnnotationConfigApplicationContext acx = new AnnotationConfigApplicationContext(AppConfig.class); //dk factoryBean,可以看出都是同一个地址,也就是单例 //dk在beanFactory里面的singletonObjects里面的lubanFactoryBean的值仍然为lubanFactoryBean //dk factoryBeanObjectCache里面存放的是FactoryBean里面的对象 //如果FactoryBean里面的对象有注入其他的东西,则容器一旦启动,factoryBeanObjectCache会存入FactoryBean里面的对象 System.out.println(acx.getBean("lubanFactoryBean")); System.out.println(acx.getBean("lubanFactoryBean"));
源码分析:
Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } //dk 这行很关键 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }
可以看到刚启动beanFactory里面的singletonObjects里面仍然为lubanFactoryBean
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { //dk 判断当前是否以&开头 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; } // 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. if (!(beanInstance instanceof FactoryBean)) { return beanInstance; } 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()); //dk 这行很关键,从单例池获取对象 object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { //dk factoryBeanObjectCache里面什么也没有,所以第一次拿不到 Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { //dk 从单例池里面获取对象,详见下文 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; }
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException { Object object; try { if (System.getSecurityManager() != null) { AccessControlContext acc = getAccessControlContext(); try { object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { //dk 调用lubanFactoryBean里面的getObject()方法,就这样拿到了对象,原路逆序返回 object = factory.getObject(); } }
//dk 如果第二次在调用则从factoryBeanObjectCache里面获取,不需要重复执行
第二种情况
假如getObject()里面的这个对象被其他的bean注入,则会在启动时候根据getObjectType来判断,并把该对象注入到容器中,也就是一启动factoryBeanObjectCache就会有一个值
@Component public class LubanFactoryBean implements FactoryBean { @Override public Object getObject() throws Exception { return new Person(); } @Override public Class<?> getObjectType() { return Person.class; } }
public class Person { }
@Service(value = "u1") //dk 注意这里如果没有value=u1的话则默认为user1,和AppConfig里面的配置冲突,直接报错 public class User1 { public void test(){ System.out.println("test1"); } @Autowired private Person person; }