整体过程
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 + "'");
}
// mbd
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.
// 得到bean的Class对象
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
// 通过resolveBeanClass操作后,mbd.hasBeanClass()==ture
if (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-injection
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 {
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);
}
}
来到方法
@Nullable
private 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作为ClassName
className = (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=true
if (!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返回$beanName
Object cacheKey = getCacheKey(beanClass, beanName);
// 判断bean不是空,或者 targetSourcedBeans 不包含该 bean
if (!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.
// 获取自定义 TargetSource
TargetSource 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 方法。
@Override
public 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);
}