整体过程
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean '" + beanName + "'");}// mbdRootBeanDefinition 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.// 得到bean的Class对象Class<?> resolvedClass = resolveBeanClass(mbd, beanName);// 通过resolveBeanClass操作后,mbd.hasBeanClass()==tureif (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.try {// 准备方法的重写,这块主要处理方法一些注入问题// https://docs.spring.io/spring-framework/docs/5.2.22.RELEASE/// spring-framework-reference/core.html#beans-factory-lookup-method-injectionmbdToUse.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 {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);}}
执行过程:
- 解析 Class;
 - override 属性进行标记及验证;
 - 解析指定bean是否存在初始化前的短路操作,可以提前生成代理对象;
 - 创建 bean;
resolveBeanClass
这块代码的作用:获取 mbd 配置的 bean 类名,将 bean 类名解析为 Class 对象,并将解析后的 Class 对象缓存以便后续复用。
 
开始
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}
来到方法
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)throws CannotLoadBeanClassException {try {// 如果定义了beanClass直接返回,通常初始化的时候是没有的if (mbd.hasBeanClass()) {return mbd.getBeanClass();}// 安全管理器的特权处理if (System.getSecurityManager() != null) {return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());}// 其他情况,也就是大部分的情况else {return doResolveBeanClass(mbd, typesToMatch);}}catch (PrivilegedActionException pae) {ClassNotFoundException ex = (ClassNotFoundException) pae.getException();throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);}catch (ClassNotFoundException ex) {throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);}catch (LinkageError err) {throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);}}
来到方法
@Nullableprivate Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)throws ClassNotFoundException {// 得到加载该bean的类加载器ClassLoader beanClassLoader = getBeanClassLoader();// 指定动态加载器ClassLoader dynamicLoader = beanClassLoader;// 表示mdb的配置的bean类名需要重新被dynamicLoader加载的标记,默认不需要boolean freshResolve = false;// 是否有匹配的类型if (!ObjectUtils.isEmpty(typesToMatch)) {// When just doing type checks (i.e. not creating an actual instance yet),// use the specified temporary class loader (e.g. in a weaving scenario).ClassLoader tempClassLoader = getTempClassLoader();if (tempClassLoader != null) {dynamicLoader = tempClassLoader;freshResolve = true;if (tempClassLoader instanceof DecoratingClassLoader) {DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;for (Class<?> typeToMatch : typesToMatch) {dcl.excludeClass(typeToMatch.getName());}}}}// 得到类名称String className = mbd.getBeanClassName();if (className != null) {// 评估beanDefinition中包含的className,如果className是可解析表达式,会对其进行解析,否则直接返回className:Object evaluated = evaluateBeanDefinitionString(className, mbd);// 如果解析后的名称和className不一样if (!className.equals(evaluated)) {// A dynamically resolved expression, supported as of 4.2...if (evaluated instanceof Class) {// 如果是Class的实例就直接返回return (Class<?>) evaluated;}else if (evaluated instanceof String) {// 如果是名称字符串,evaluated作为ClassNameclassName = (String) evaluated;// 让dynamicLoader重新加载freshResolve = true;}else {// 否则异常throw new IllegalStateException("Invalid class name expression result: " + evaluated);}}// 如果mdb的配置的bean类名需要重新被dynameicLoader加载if (freshResolve) {// When resolving against a temporary class loader, exit early in order// to avoid storing the resolved Class in the bean definition.if (dynamicLoader != null) {try {// 加载得到Class对象return dynamicLoader.loadClass(className);}catch (ClassNotFoundException ex) {if (logger.isTraceEnabled()) {logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);}}}// 加载得到Class对象return ClassUtils.forName(className, dynamicLoader);}}// 到这里表示,评估后的Class名称和className一样。// 使用classLoader加载当前BeanDefinitiond对象所配置的Bean类名的Class对象// Resolve regularly, caching the result in the BeanDefinition...return mbd.resolveBeanClass(beanClassLoader);}
prepareMethodOverrides()
https://docs.spring.io/spring-framework/docs/5.2.22.RELEASE/spring-framework-reference/core.html#beans-factory-lookup-method-injection
这块主要处理的配置文件中的 lookup-method 和 replace-method 这样的属性。
见:
解析 lookup-method
解析 replaced-method
// Prepare method overrides.try {// 准备方法的重写,这块主要处理方法一些注入问题mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}
来到方法
public void prepareMethodOverrides() throws BeanDefinitionValidationException {// Check that lookup methods exist and determine their overloaded status.if (hasMethodOverrides()) {getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);}}
来到方法
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());if (count == 0) {throw new BeanDefinitionValidationException("Invalid method override: no method with name '" + mo.getMethodName() +"' on class [" + getBeanClassName() + "]");}else if (count == 1) {// Mark override as not overloaded, to avoid the overhead of arg type checking.mo.setOverloaded(false);}}
在 Spring 配置中存在 lookup-method 和 replace-method 两个配置功能,而这两个配置的加载其实就是将配置统一存放在BeanDefinition 中的 methodOverrides 属性里,这两个功能实现原理其实是在 bean实例化的时候如果检测到存在 methodOverrides 属性,会动态地为当前 bean 生成代理并使用对应的拦截器为 bean 做增强处理。
对于方法的匹配来讲,如果一个类中存在若干个重载方法,那么在函数调用及增强的时候还需要根据参数类型进行匹配,来最终确认当前调用的到底是哪个函数。在这里将一部分匹配工作完成了,如果当前类中的方法只有一个,那么就设置重载该方法没有被重载,这样在后续调用的时候便可以直接使用找到方法,而不需要进行方法的参数匹配验证了,而且还可以提前对方法存在性进行验证,正可谓一箭雕。
resolveBeforeInstantiation(beanName, mbdToUse)
这个阶段如果满足条件,就可以直接产生代理对象。我们熟知的 AOP 功能就是基于这里的判断的。
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;}}
来到方法 resolveBeforeInstantiation.
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;// 如果bean已经产生那么mbd.beforeInstantiationResolved=trueif (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {// 获取目标对象的Class对象Class<?> targetType = determineTargetType(beanName, mbd);if (targetType != null) {// 执行bean初始化前置处理器bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean != null) {// 如果产生了对象,那么继续执行初始化后处理器bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}mbd.beforeInstantiationResolved = (bean != null);}return bean;}
实例化前处理器
实例化前的处理器,bean 的实例化前调用,也就是将 AbsractBeanDefinition 转换为 BeanWrapper 前的处理。这个时候可以修改 BeanDefinition,那么我们得到的 bean 可能就是经过修改后的 bean 。
进入方法 applyBeanPostProcessorsBeforeInstantiation.
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {for (BeanPostProcessor bp : getBeanPostProcessors()) {// 判断InstantiationAwareBeanPostProcessor的实例if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);if (result != null) {return result;}}}return null;}
那么 InstantiationAwareBeanPostProcessor 的实例就会继续执行 postProcessBeforeInstantiation 方法。
比如我们后创建 AOP 代理的 AbstractAutoProxyCreator 。
可以看出,如果提供了自定义 TargetSource ,那么这个前置处理器就直接返回了代理对象。
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {// 获取缓存的key,普通bean返回beanName,FactoryBean返回$beanNameObject cacheKey = getCacheKey(beanClass, beanName);// 判断bean不是空,或者 targetSourcedBeans 不包含该 beanif (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {// 如果advisedBeans包含if (this.advisedBeans.containsKey(cacheKey)) {return null;}// 如果是aop相关的基础类,或者是应该跳过不处理的类if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {// 加入缓存advisedBeans,表示已经处理完毕,不需要代理this.advisedBeans.put(cacheKey, Boolean.FALSE);return null;}}// Create proxy here if we have a custom TargetSource.// Suppresses unnecessary default instantiation of the target bean:// The TargetSource will handle target instances in a custom fashion.// 获取自定义 TargetSourceTargetSource targetSource = getCustomTargetSource(beanClass, beanName);if (targetSource != null) {if (StringUtils.hasLength(beanName)) {// 不为空加入缓存this.targetSourcedBeans.add(beanName);}// 创建代理对象Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}return null;}
实例化后处理器
Spring 中的规则是在 bean 的初始化后尽可能保证将注册的后处理器的 postProcessAfterInitialization 方法应用到该 bean中,因为如果返回的bean不为空,那么便不会再次经历普通 bean 的创建过程,所以只能在这里应用后处理器的 postProcessAfterInitialization 方法。
@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}
doCreateBean
如果上面的前置处理器resolveBeforeInstantiation没有产生代理对象的话,那么接下来就开始创建对象了。
进入下一个阶段 doCreateBean。
try {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);}
