一、前言
在上一节中我们介绍了在Spring 解析xml配置文件的时候,给我们往容器中生成了很多BeanDefinition,其中最重要的是advice对象,而advice对象最外层是用一个advisor对象包裹起来,而我们的advice对象的创建需要三个参数,第一个是MethodLocatingFactoryBean,第二个是AspectJExpressionPointcut对象,第三个是SimpleBeanFactoryAwareAspectInstanceFactory对象,如下图:
具体的BeanDefinition如下图:
Spring解析配置文件只是把这些advisor的BeanDefinition提前创建好了,但是这些对象创建放进去容器了吗?很明显是没有的,我们知道在refresh()方法中,finishBeanFactoryInitialization会提前创建非懒加载的bean,继续往下看。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 为上下文初始化类型转换器
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// 如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器,主要用于注解属性值的解析
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 尽早初始化loadTimeWeaverAware bean,以便尽早注册它们的转换器
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
// 禁止使用临时类加载器进行类型匹配
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 冻结所有的bean定义,说明注册的bean定义将不被修改或任何进一步的处理
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化剩下的单例对象
beanFactory.preInstantiateSingletons();
}
在preInstantiateSingletons实例化剩下的Bean。
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// 将所有BeanDefinition的名字创建一个集合
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 触发所有非延迟加载单例bean的初始化,遍历集合的对象
for (String beanName : beanNames) {
// 合并父类BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 条件判断,抽象,单例,非懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是否实现了FactoryBean接口
if (isFactoryBean(beanName)) {
// 根据&+beanName来获取具体的对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
// 进行类型转换
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
// 判断这个FactoryBean是否希望立即初始化
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());
}
// 如果希望急切的初始化,则通过beanName获取bean实例
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// 如果beanName对应的bean不是FactoryBean,只是普通的bean,通过beanName获取bean实例
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
// 遍历beanNames,触发所有SmartInitializingSingleton的后初始化回调
for (String beanName : beanNames) {
// 获取beanName对应的bean实例
Object singletonInstance = getSingleton(beanName);
// 判断singletonInstance是否实现了SmartInitializingSingleton接口
if (singletonInstance instanceof SmartInitializingSingleton) {
// 类型转换
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
// 触发SmartInitializingSingleton实现类的afterSingletonsInstantiated方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
我们接下来实例化的是logUtil这个类,以下就进入了熟悉的getBean方法,如果还不熟悉Spring生命周期的可以去看一下之前的博客,接下来我们继续放下跟。
@Override
public Object getBean(String name) throws BeansException {
// 此方法是实际获取bean的方法,也是触发依赖注入的方法
return doGetBean(name, null, null, false);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
/**
* 提取对应的beanName,很多同学可能会认为此处直接使用即可,为什么还要进行转换呢,原因在于当bean对象实现FactoryBean接口之后就会变成&beanName,同时如果存在别名,也需要把别名进行转换*/
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
/**提前检查单例缓存中是否有手动注册的单例对象,跟循环依赖有关联*/
Object sharedInstance = getSingleton(beanName);
// 如果bean的单例对象找到了,且没有创建bean实例时要使用的参数
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 + "'");
}
}
// 返回对象的实例,很多同学会理解不了这句话存在的意义,当你实现了FactoryBean接口的对象,需要获取具体的对象的时候就需要此方法来进行获取了
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 当对象都是单例的时候会尝试解决循环依赖的问题,但是原型模式下如果存在循环依赖的情况,那么直接抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 如果bean定义不存在,就检查父工厂是否有
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果beanDefinitionMap中也就是在所有已经加载的类中不包含beanName,那么就尝试从父容器中获取
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 获取name对应的规范名称【全类名】,如果name前面有'&',则会返回'&'+规范名称【全类名】
String nameToLookup = originalBeanName(name);
// 如果父工厂是AbstractBeanFactory的实例
if (parentBeanFactory instanceof AbstractBeanFactory) {
// 调用父工厂的doGetBean方法,就是该方法。【递归】
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
// 如果有创建bean实例时要使用的参数
// Delegation to parent with explicit args. 使用显示参数委派给父工厂
// 使用父工厂获取该bean对象,通bean全类名和创建bean实例时要使用的参数
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
// 没有创建bean实例时要使用的参数 -> 委托给标准的getBean方法。
// 使用父工厂获取该bean对象,通bean全类名和所需的bean类型
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
// 使用父工厂获取bean,通过bean全类名
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 如果不是做类型检查,那么表示要创建bean,此处在集合中做一个记录
if (!typeCheckOnly) {
// 为beanName标记为已经创建(或将要创建)
markBeanAsCreated(beanName);
}
try {
// 此处做了BeanDefinition对象的转换,当我们从xml文件中加载beandefinition对象的时候,封装的对象是GenericBeanDefinition,
// 此处要做类型转换,如果是子类bean的话,会合并父类的相关属性
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查mbd的合法性,不合格会引发验证异常
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 如果存在依赖的bean的话,那么则优先实例化依赖的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
// 如果存在依赖,则需要递归实例化依赖的bean
for (String dep : dependsOn) {
// 如果beanName已注册依赖于dependentBeanName的关系
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册各个bean的依赖关系,方便进行销毁
registerDependentBean(dep, beanName);
try {
// 递归优先实例化被依赖的Bean
getBean(dep);
}
// 捕捉为找到BeanDefinition异常:'beanName'依赖于缺少的bean'dep'
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
// 创建bean的实例对象
if (mbd.isSingleton()) {
// 返回以beanName的(原始)单例对象,如果尚未注册,则使用singletonFactory创建并注册一个对象:
sharedInstance = getSingleton(beanName, () -> {
try {
// 为给定的合并后BeanDefinition(和参数)创建一个bean实例
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
// 显示地从单例缓存中删除实例:它可能是由创建过程急切地放在那里,以允许循环引用解析。还要删除
// 接收到该Bean临时引用的任何Bean
// 销毁给定的bean。如果找到相应的一次性Bean实例,则委托给destoryBean
destroySingleton(beanName);
// 重新抛出ex
throw ex;
}
});
// 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
// FactoryBean会直接返回beanInstance实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 原型模式的bean对象创建
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
// 它是一个原型 -> 创建一个新实例
// 定义prototype实例
Object prototypeInstance = null;
try {
// 创建Prototype对象前的准备工作,默认实现将beanName添加到prototypesCurrentlyInCreation中
beforePrototypeCreation(beanName);
// 为mbd(和参数)创建一个bean实例
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 创建完prototype实例后的回调,默认是将beanName从prototypesCurrentlyInCreation移除
afterPrototypeCreation(beanName);
}
// 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
// FactoryBean会直接返回beanInstance实例
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// 指定的scope上实例化bean
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
// 从scopes中获取scopeName对于的Scope对象
Scope scope = this.scopes.get(scopeName);
// 如果scope为null
if (scope == null) {
// 抛出非法状态异常:没有名为'scopeName'的scope注册
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 从scope中获取beanName对应的实例对象
Object scopedInstance = scope.get(beanName, () -> {
// 创建Prototype对象前的准备工作,默认实现 将beanName添加到prototypesCurrentlyInCreation中
beforePrototypeCreation(beanName);
try {
// 为mbd(和参数)创建一个bean实例
return createBean(beanName, mbd, args);
}
finally {
// 创建完prototype实例后的回调,默认是将beanName从prototypesCurrentlyInCreation移除
afterPrototypeCreation(beanName);
}
});
// 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
// FactoryBean会直接返回beanInstance实例
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
// 捕捉非法状态异常
// 抛出Bean创建异常:作用域 'scopeName' 对于当前线程是不活动的;如果您打算从单个实例引用它,请考虑为此
// beanDefinition一个作用域代理
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
// 捕捉获取Bean对象抛出的Bean异常
// 在Bean创建失败后,对缓存的元数据执行适当的清理
cleanupAfterBeanCreationFailure(beanName);
// 重新抛出ex
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
// 检查requiredType是否与实际Bean实例的类型匹配
// 如果requiredType不为null&&bean不是requiredType的实例
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// 获取此BeanFactory使用的类型转换器,将bean转换为requiredType
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
// 如果convertedBean为null
if (convertedBean == null) {
// 抛出Bean不是必要类型的异常
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
// 返回convertedBean
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
// 将bean返回出去
return (T) bean;
}
很明显这个Bean在缓存中是没有的,所以就会进入的createBean中去。
这不知道大家是否记得,resolveBeforeInstantiation,这里是给一个机会BPP去创建对象。
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// 如果beforeInstantiationResolved值为null或者true,那么表示尚未被处理,进行后续的处理
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
// 确认beanclass确实在此处进行处理
// 判断当前mbd是否是合成的,只有在实现aop的时候synthetic的值才为true,并且是否实现了InstantiationAwareBeanPostProcessor接口
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 获取类型
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
// 是否解析了
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
里面是两个关键条件,第一个条件mbd.isSynthetic(),是否是合成的,不知道在上一篇博客大家是否注意到了生成MethodLocadingBeanFactory中的属性设置,我们来看下。
这里就是标记是Spring合成的BeanDefinition,第二个条件是hasInstantiationAwareBeanPostProcessors(),这个条件就是在refresh方法中注册BPP的时候设置的属性值。继续往下跟。
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
这里就是调用对应的BPP,这里我们直接看我们在解析配置文件的时候注入的AbstractAutoProxyCreator。
我们看下isInfrastructureClass,判断是否是基础的bean。
@Override
protected boolean isInfrastructureClass(Class<?> beanClass) {
// Previously we setProxyTargetClass(true) in the constructor, but that has too
// broad an impact. Instead we now override isInfrastructureClass to avoid proxying
// aspects. I'm not entirely happy with that as there is no good reason not
// to advise aspects, except that it causes advice invocation to go through a
// proxy, and if the aspect implements e.g the Ordered interface it will be
// proxied by that interface and fail at runtime as the advice method is not
// defined on the interface. We could potentially relax the restriction about
// not advising aspects in the future.
return (super.isInfrastructureClass(beanClass) ||
(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
我们这里创建的是logUtil很明显不是基础bean,接下来看shouldSkip的逻辑。
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
// 判断这些创建的advisor的切面对象是否是当前bean,如果是则返回tre,表示不用创建代理对象
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
findCandidateAdvisors这里是查找对应advisor对象,我们继续往下看这个方法。
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 找到系统中实现了Advisor接口的bean
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
// 找到系统中使用@Aspect标注的bean,并且找到该bean中使用@Before,@After等标注的方法,
// 将这些方法封装为一个个Advisor
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
// 获取所有的增强处理
return this.advisorRetrievalHelper.findAdvisorBeans();
}
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
// 获取当前BeanFactory中所有实现了Advisor接口的bean的名称
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
// 对获取到的实现Advisor接口的bean的名称进行遍历
List<Advisor> advisors = new ArrayList<>();
// 循环所有的beanName,找出对应的增强方法
for (String name : advisorNames) {
// isEligibleBean()是提供的一个hook方法,用于子类对Advisor进行过滤,这里默认返回值都是true
if (isEligibleBean(name)) {
// 如果当前bean还在创建过程中,则略过,其创建完成之后会为其判断是否需要织入切面逻辑
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
// 将当前bean添加到结果中
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
// 对获取过程中产生的异常进行封装
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
这里就获取得到我们在之前配置文件中解析生成的所有advisor对象,获取得到这些对象之后,然后就会通过getBean来生成这些对象。
这里思考一个问题,我们创建一个advisor对象,我们来看下advisor对象的构造函数。
很明显,我们创建advisor对象,那么就需要给他提前准备advice对象,我们接下继续看advice对象的构造函数。
我们创建advice对象就需要提前创建好MethodLocadingBeanFactory对象,以及 AspectJExpressionPointcut和SimpleBeanFactoryAwareAspectInstanceFactory对象。
所以总结一下,在AspectJAwareAdvisorAutoProxyCreator会找出所有的advisor对象,然后创建他们并且放入到缓存中,那么在创建advisor对象的时候也会提前创建advice对象,创建advice对象也会提前创建MethodLocadingBeanFactory对象,以及 AspectJExpressionPointcut和SimpleBeanFactoryAwareAspectInstanceFactory对象,这是一个递归调用getBean的过程。至于具体在哪调用,大家可以去看下我之前IOC生命周期的博客。
这里就提前把Advisor对象给提前创建好了,然后就会判断当前类是否是切面对象,如果是切面对象,那就是应该跳过不创建代理对象。
很明显logUtil就需要跳过并且返回null,所以在 resolveBeforeInstantiation方法中,如果是第一次调用那么他就会去寻找所有的Advisor对象,如果这些Advisor对象没有创建,那么就会创建他们,如果创建了那么就直接从容器中获取,如果获取得到了advisor对象,那么就会判断当前的对象是否是切面对象,如果是切面对象,那么就会跳过不创建代理对象。