Spring之根据BeanDefinition创建Bean
前面已经说明白了所有的BeanDefinition的扫描过程以及配置类的代理过程之后,下面就给对所有的BeanDefinition进行实例化了。
那么如何来进行实例化阶段的呢
从方法注释上来看,是实例化所有的非懒加载的单例bean。那么直接来到org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
这里主要分成了两个大的步骤:
一、循环遍历并创建非懒加载的单例bean;
二、所有的非懒加载的单例bean创建完成之后,执行单例实例化之后的方法;
二、创建非懒加载的单例Bean
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
2.1、合并BeanDefinition的意义
是否还记得前面讲过的抽象父BeanDefinition和具体的子BeanDefinition,这里就有了具体的体现。
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
GenericBeanDefinition parentGenericBeanDefinition = new GenericBeanDefinition();
parentGenericBeanDefinition.setInitMethodName("init");
parentGenericBeanDefinition.setLazyInit(false);
parentGenericBeanDefinition.setPrimary(true);
parentGenericBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
parentGenericBeanDefinition.setDestroyMethodName("destroy");
parentGenericBeanDefinition.setAbstract(true);
applicationContext.registerBeanDefinition("parent",parentGenericBeanDefinition);
GenericBeanDefinition aGenericBeanDefinition = new GenericBeanDefinition();
aGenericBeanDefinition.setBeanClass(A.class);
aGenericBeanDefinition.setParentName("parent");
applicationContext.registerBeanDefinition("a",aGenericBeanDefinition);
GenericBeanDefinition bGenericBeanDefinition = new GenericBeanDefinition();
bGenericBeanDefinition.setBeanClass(B.class);
bGenericBeanDefinition.setParentName("parent");
applicationContext.registerBeanDefinition("b",bGenericBeanDefinition);
applicationContext.refresh();
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println("bean的名称是:"+beanDefinitionName);
}
}
}
因为是两个beanName叫parent和b的BeanDefinition,但是因为存在着抽象的BeanDefinition,无法创建出来Bean,所以首先需要将抽象BeanDefinition给筛选掉,其次因为父子BeanDefinition中存在着继承关系,所以需要将子BeanDefinition继承父BeanDefinition中的属性设置到子BeanDefinition中来,而这里的合并BeanDefinition就是为了来实现这样的逻辑。
对于合并了的bean来说,会放入到mergedBeanDefinitions集合中来,而后续的操作就是围绕着mergedBeanDefinitions来进行操作了。
2.2、单例bean
只有单例的BeanDefinition才会在这个阶段中称为候选的bean
2.3、非懒加载
懒加载强调的是在某一个过程之后进行加载,而非懒加载强调的是开始阶段就要来进行创建。
2.4、源代码
三、FactoryBean
3.1、官方解释
看看官方对FactoryBean类的解释
/**
* Interface to be implemented by objects used within a {@link BeanFactory} which
* are themselves factories for individual objects. If a bean implements this
* interface, it is used as a factory for an object to expose, not directly as a
* bean instance that will be exposed itself.
*
* <p><b>NB: A bean that implements this interface cannot be used as a normal bean.</b>
* A FactoryBean is defined in a bean style, but the object exposed for bean
* references ({@link #getObject()}) is always the object that it creates.
*
* <p>FactoryBeans can support singletons and prototypes, and can either create
* objects lazily on demand or eagerly on startup. The {@link SmartFactoryBean}
* interface allows for exposing more fine-grained behavioral metadata.
*
* <p>This interface is heavily used within the framework itself, for example for
* the AOP {@link org.springframework.aop.framework.ProxyFactoryBean} or the
* {@link org.springframework.jndi.JndiObjectFactoryBean}. It can be used for
* custom components as well; however, this is only common for infrastructure code.
*
* <p><b>{@code FactoryBean} is a programmatic contract. Implementations are not
* supposed to rely on annotation-driven injection or other reflective facilities.</b>
* {@link #getObjectType()} {@link #getObject()} invocations may arrive early in the
* bootstrap process, even ahead of any post-processor setup. If you need access to
* other beans, implement {@link BeanFactoryAware} and obtain them programmatically.
*
* <p><b>The container is only responsible for managing the lifecycle of the FactoryBean
* instance, not the lifecycle of the objects created by the FactoryBean.</b> Therefore,
* a destroy method on an exposed bean object (such as {@link java.io.Closeable#close()}
* will <i>not</i> be called automatically. Instead, a FactoryBean should implement
* {@link DisposableBean} and delegate any such close call to the underlying object.
*
* <p>Finally, FactoryBean objects participate in the containing BeanFactory's
* synchronization of bean creation. There is usually no need for internal
* synchronization other than for purposes of lazy initialization within the
* FactoryBean itself (or the like).
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 08.03.2003
* @param <T> the bean type
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.aop.framework.ProxyFactoryBean
* @see org.springframework.jndi.JndiObjectFactoryBean
*/
可以得到以下信息:
- 1、FactoryBean是一个创建bean的工厂;
- 2、如果一个类是实现了FactoryBean接口,那么利用接口中的getObject()方法来创建bean;
- 3、FactoryBean是spring中具有特殊意义的一个类;
3.2、作用
那么怎么特殊呢?利用这个类可以获取得到两个Bean
3.3、示例代码
示例代码:
public class AService {}
@Component
public class MyFactoryBean implements FactoryBean<AService> {
@Override
public AService getObject() throws Exception {
return new AService();
}
@Override
public Class<?> getObjectType() {
return AService.class;
}
}
对应的测试代码:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
applicationContext.refresh();
System.out.println(applicationContext.getBean("myFactoryBean"));
System.out.println(applicationContext.getBean("&myFactoryBean"));
打印效果如下所示:
com.guang.spring.service.AService@2eda0940
com.guang.spring.factorybean.MyFactoryBean@3578436e
从上面的测试代码中可以知道,传递的bean的名称不同,得到的bean也是不同的。
加了&的符号的,获取得到的是MyFactoryBean类型的;而没有加&的是getObejct返回的类型。
所以既然有两种名称,而对于getBean方法来说,是公共的方法,所以spring也应该提供对两个不同名称的bean进行解析判断。
3.4、SmartFactoryBean
public interface SmartFactoryBean<T> extends FactoryBean<T> {
default boolean isPrototype() {
return false;
}
default boolean isEagerInit() {
return false;
}
是FactoryBean的拓展接口,为了能够提前实例化FactoryBean对应的getObject()方法对应的bean提前实例化。
四、SmartInitializingSingleton
在所有的单例的非懒加载的bean完成完整的生命周期后,调用实现SmartInitializingSingleton接口的bean的初始化完成方法。