Spring源码(十五)createBean方法
createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 锁定class,根据设置的class属性或者根据className来解析class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
// 进行条件筛选,重新赋值RootBeanDefinition,并设置BeanClass属性
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
// 重新创建一个RootBeanDefinition对象
mbdToUse = new RootBeanDefinition(mbd);
// 设置BeanClass属性值
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
// 验证及准备覆盖的方法,lookup-method replace-method,当需要创建的bean对象中包含了lookup-method和replace-method标签的时候,会产生覆盖操作
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 给BeanPostProcessors一个机会来返回代理来替代真正的实例,应用实例化前的前置处理器,用户自定义动态代理的方式,针对于当前的被代理类需要经过标准的代理流程来创建对象
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 实际创建bean的调用
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
进入到resolveBeanClass方法中。beanClass为String类型的。
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
throws CannotLoadBeanClassException {
try {
// 判断mbd的定义信息中是否包含beanClass,并且是Class类型的,如果是直接返回,否则的话进行详细的解析
if (mbd.hasBeanClass()) {
// 如果mbd指定了bean类
return mbd.getBeanClass();
}
// 判断是否有安全管理器
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
// 进行详细的处理解析过程
return doResolveBeanClass(mbd, typesToMatch);
}
}
这里进行了判断是否有安全检查管理器,如果有,那么就获取权限,并用doResolveBeanClass,这个方法里面是native,用C写的,就略过;如果没有,这里的resolveBeanClass方法就不一样了,此方法调用了resolveBeanClass方法,这里就是ForName,将String类型的class转换为类。
然后有了这个Class对象,如果我们想反射,那么就要用new Instance,可以直接返回对象了。但是这里并没有这么做。
下面,mdbToUse.prepareMethodOverrides方法,这里有两个标签,一个lookup-method,一个replace-method。
这里设置了标志位,标记methodOverride暂未被覆盖,避免参数类型检查的开销。只是标识了一下,在后面实例化时,再调用。
当需要创建bean对象,包含了lookup method与replace-method,回产生覆盖操作。
接下来继续,到doCreateBean方法了,然后调用了createBeanInstance方法,再调用了instantiateBean方法,再调用instantiate方法。到了fasle,再进入instantiateWithMethodInjection方法。再进入CglibSubclassCreator.instance方法,
通过拦截器方式每次需要的时候创建最新的对象,而不会把原型对象缓存起来。
如果不用这种方式,虽然取得的原型,但是每次拿的都是一样的。因为创建的apple会被缓存,而原型bean也会被缓存去,不能每次获得新的banana对象,而配了lookup的话,每次获取到的就是最新的结果,get重新获取,因为缓存中没有。
用gebean的获取的时候,实际上一级缓存中放的是cglib的拦截器。用getFruit方法进去时,直接到iCGLIBSubClassing方法的ntercept方法中了,lo包括apple与方法getFruit,这里会用getBean去创建apple对象了。
继续往下,resolveBeforeInstantiation,使用代理的方式返回bean,可以在这里自己实现动态代理的东西。
这里自定义了实现此方法,后续的doCreateBean就不用走了,直接走上面代理出来的bean对象。(取决于BPP是否包含InstantiationAwareBeanPostProcessor)。一般这里不会进行处理的,为空。
下面就要进入到doCreateBean核心创建对象方法中了。
总结
上面流程需要注意的是lookup-method与replace-method的使用。它们的作用是处理单例情况下引用了多例的方式。
resolveBeforeInstantiation这种方法可以提前创建用户自定义的代理对象。