zoukankan      html  css  js  c++  java
  • 深入理解 Spring finishBeanFactoryInitialization

    源码入口

    上篇博文中我们看到了将Spring环境中的 BeanPostProcessor找出来,添加到BeanFactory中的beanPostProcessors中,统一维护,本片博文继续往下拓展,看下Spring如何实例化bean,以及如何实现在bean的实例化通过各种各样的后置处理器完成bean的增强

    所以本次的程序入口是AbstractApplicationContext中的finishBeanFactoryInitialization(beanFactory);,源码如下,主要做了如下几件事

    
    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));
    	}
    
        // 检查上下文中是否存在类型转换器
    	if (!beanFactory.hasEmbeddedValueResolver()) {
    		beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    	}
        // 尽早初始化LoadTimeWeaverAware bean,以便尽早注册它们的转换器。
    	// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    	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的定义数据
    	beanFactory.freezeConfiguration();
    
    	// Instantiate all remaining (non-lazy-init) singletons.
        // 准备实例化bean
    	beanFactory.preInstantiateSingletons();
    }
    

    我们着重看他是如何创建实例化bean的,跟进beanFactory.preInstantiateSingletons();,调用beanFactory的方法准备实例化bean, 这个beanFactory就是Spring默认是bean工厂, DefaultListableBeanFactory, 源码如下:方法不算很长,逻辑也很清楚, 一开始Spring取出当前上下文中所有的BeanName列表,因为在执行到这里之前,已经完成包扫描了所以说这个盛放beanName的list里面存放的就是所有的需要实例化的对象的全集,包含Spring自己的,和程序员自己添加的还包含Aspectj的

    所以说,当前方法的目标很明了,就是遍历这个list中的每一个beanName,然后实例化当前beanName相应的bean

    当然,如果想实例化,前提是不能是抽象类,不能是接口,非懒加载, 而且针对FactoryBean还有不同的处理模式

    public void preInstantiateSingletons() throws BeansException {
    if (logger.isDebugEnabled()) {
    	logger.debug("Pre-instantiating singletons in " + this);
    }
    //所有bean的名字
    // 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.
    //todo 遍历一个副本以允许init方法,而init方法反过来注册新的bean定义。
    // todo 盛放所有的beanName,所有的需要实例化的beanName都在这里,包括Spring断断续续添加的, Aspectj的, 程序员通过注解标识的
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    
    // Trigger initialization of all non-lazy singleton beans...
    // todo 触发所有非延迟加载单例beans的初始化,主要步骤为调用getBean
    for (String beanName : beanNames) {
    
    	// todo 合并父类BeanDefinition,可以进入查看
    	RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    
    	//todo 三个条件,抽象,单例,非懒加载
    	if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    
    		if (isFactoryBean(beanName)) {
    			Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
    			// todo 如果是FactoryBean则加上&
    			// todo 检验是否是 FactoryBean 类型的对象
    			if (bean instanceof FactoryBean) {
    				final 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 {
    			// todo 因为我们没有添加FactoryBean类型的对象, 一般都会进入这个getBean
    			getBean(beanName);
    		}
    	}
    }
    

    下面接着跟进getBean(beanName);方法,顾名思义获取Bean,再往下跟下去,就算是本文的正文开始部分了,但是我想在这里提醒自己,一个比较有分量的剧透吧,当前的getBean(beanName)它是有返回值的,一会当我们往下跟进的是时候会发现会存在递归的现象,这一点巧妙的实现了@Autowired处理setter方式实现循环引用

    ok,现在继续看代码,经过了几个空方法的传递,我们来到下面的代码中,它主要做了如下几件事

    首先将传递进来的name转换成了beanName

    原因1: FactoryBean的实现类的存储方式和其他的类完全相同,添加上&是获取不到的, 因此我们将&去掉 原因2: 解决别名的问题

    为什么在创建bean之前先调用getSingleton()?

    回想一下,现在是Spring启动的过程中,是在准备实例化bean,为什么一开始就来getSingleton(),跟进源码查看这个方法,它最终实现中有一行代码是这样的Object singletonObject = this.singletonObjects.get(beanName);而这个singletonObjects就是微观层面的IOC容器,循环创建刚开始时,IOC确实是空的,但是我前面存在剧透,一开始的getBean()方法是存在递归调用现象的,直接举2个例子: 第一:假如现在在实例化A,结果有发现需要给A注入B, 那Spring是不是得获得B,怎么获得呢? 递归使用getBean(BName)完成, 第二个例子: A被添加上了@Lazy注解,是懒加载的,但是终究有一个会通过getBean(AName)获取A,这是发现A是实例化需要B,B肯定已经实例化完事了,同样是通过递归getBean(BName)实现注入, 在这两个过程中就是getSingleton()保证不会重复创建已经存在的实例

    我们关注的重点其实是第二个getSingleton(beanName()->{xxx})

    在第二个getSingleton()方法中才是真正的去实例化bean的方法

    最后,在当前的方法最后将bean返回了

    前面我就是说过了,getBean(beanName)存在递归调用的情况,为什么我会一直说这个事呢,因为如果不知道这个事的话,这些代码看起来是没有头绪的,但是明白这个事,看代码就变得很有逻辑,我在简单总结一下怎个玩这个递归呢? 假设现在通过getBean(AName)来注入A对象,但是呢发现了A依赖B对象,于是在getBean(AName)里面调用getBean(BName),通过这个方法返回出B对象完成A的注入

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
    	@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    
    // 将传递进来的name
    final String beanName = transformedBeanName(name);
    Object bean;
    
    // Eagerly check singleton cache for manually registered singletons.
    // 及早的检查一下有没有已经注册了的单例对象
    Object sharedInstance = getSingleton(beanName);// todo ::: name=myService时,这次来调用的就是 DefaultSingletonBeanRegistry中的 getSingleton() , 不同之处是多传递了一个true
    if (sharedInstance != null && args == null) {
        // 如果存在的话,将其取出赋值给bean,后续直接返回这个bean
    	bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } else {
    	// Fail if we're already creating this bean instance:
    	// We're assumably within a circular reference.
        // 来到这里就说明要获取的bean还没有实例化过
        // 于是检验一下,如果是原形,直接抛异常
    	if (isPrototypeCurrentlyInCreation(beanName)) {
    		throw new BeanCurrentlyInCreationException(beanName);
    	}
    
    	// Check if bean definition exists in this factory.
        // 检查是否存在默认的父工厂
    	BeanFactory parentBeanFactory = getParentBeanFactory();
    	if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    		// Not found -> check parent.
    		String nameToLookup = originalBeanName(name);
    		if (parentBeanFactory instanceof AbstractBeanFactory) {
    			return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
    					nameToLookup, requiredType, args, typeCheckOnly);
    		}
    		else if (args != null) {
    			// Delegation to parent with explicit args.
    			return (T) parentBeanFactory.getBean(nameToLookup, args);
    		}
    		else {
    			// No args -> delegate to standard getBean method.
    			return parentBeanFactory.getBean(nameToLookup, requiredType);
    		}
    	}
    
    	if (!typeCheckOnly) {
    	    // 将当前的beanName存放到AlreadeyCreated这个set集中,标识这个bean被创建了
    		markBeanAsCreated(beanName);
    	}
    
    	try {
    		final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    		checkMergedBeanDefinition(mbd, beanName, args);
    
    		// Guarantee initialization of beans that the current bean depends on.
    		// 确保当前bean所依赖的bean都已经初始化好了
    		String[] dependsOn = mbd.getDependsOn();
    		if (dependsOn != null) {
    			for (String dep : dependsOn) {
    				if (isDependent(beanName, dep)) {
    					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    							"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
    				}
    				registerDependentBean(dep, beanName);
    				try {
    					getBean(dep);
    				}
    				catch (NoSuchBeanDefinitionException ex) {
    					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    							"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
    				}
    			}
    		}
    
    		// Create bean instance.
    		if (mbd.isSingleton()) {
    		  // 实例化bean
    			sharedInstance = getSingleton(beanName, () -> { 
    		            // 真正的完成bean的创建
    					return createBean(beanName, mbd, args);
    			
    			});
    
    			bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    		}
            // 下面是进行其他的检查工作,这里不再深究了
    		else if (mbd.isPrototype()) {
    			// It's a prototype -> create a new instance.
    			Object prototypeInstance = null;
    			try {
    				beforePrototypeCreation(beanName);
    				prototypeInstance = createBean(beanName, mbd, args);
    			}
    			finally {
    				afterPrototypeCreation(beanName);
    			}
    			bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    		}
    
    		else {
    			String scopeName = mbd.getScope();
    			final Scope scope = this.scopes.get(scopeName);
    			if (scope == null) {
    				throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
    			}
    			try {
    				Object scopedInstance = scope.get(beanName, () -> {
    					beforePrototypeCreation(beanName);
    					try {
    						return createBean(beanName, mbd, args);
    					}
    					finally {
    						afterPrototypeCreation(beanName);
    					}
    				});
    				bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    			}
    			catch (IllegalStateException ex) {
    				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) {
    		cleanupAfterBeanCreationFailure(beanName);
    		throw ex;
    	}
    }
    
    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && !requiredType.isInstance(bean)) {
    	try {
    		T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
    		if (convertedBean == null) {
    			throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    		}
    		return convertedBean;
    	}
    	catch (TypeMismatchException ex) {
    		if (logger.isDebugEnabled()) {
    			logger.debug("Failed to convert bean '" + name + "' to required type '" +
    					ClassUtils.getQualifiedName(requiredType) + "'", ex);
    		}
    		throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    	}
    }
    return (T) bean;
    }
    

    经过了上面一顿扯,然后我们继续往下跟,看看createBean(beanName, mbd, args)方法中是如何实例化我们的Bean的, 上面的方法是在AbstractBeanFactory中,createBean(beanName, mbd, args)是它的抽象方法, 那实现类是哪个呢?

    AbstractAutowireCapableBeanFactory,隆重的夸一下这个类,Spring都称赞这个类是有有才华的

    todo 总结这个类

    在这个方法中,主要做了两件事:两件大事!!!

    第一件大事:

    在实例化Bean前,第一次调用后置处理器, 这件大事绝对是有历史意义的!!!为啥呢?大家想想,bean还没有创建呢!就已经可以插手bean的创建过程了,不是很刺激吗?接着看回调了什么后置处理器呢? Spring会循环所有的处理器检查当前被遍历的处理器是否是InstantiationAwareBeanPostProcessor类型的,如果是的话呢,就执行这个后置处理器的postProcessBeforeInstantiation(beanClass, beanName);方法

    这个postProcessBeforeInstantiation()是允许有返回值的,大家可以想想,这一点是不是有点可怕? 事实也是这样,后置处理器的目的是为了增强对象,而我们却可以在这里返回一个任何东西,狸猫换台子替换掉原始的,还没有被创建的对象,还有一点,就是一旦我们在这里真的是没有返回null,那后续Spring就没有义务在去为我们创建本来应该创建的对象了,代码通过if-else的选择分支会使得当前的对象不再经历其他后置处理器的增强,最终执行它父类的postProcessorAfterInitialization()

    补充一点,我们通过@EnableAspectjAutoProxy添加到Spring上下文中的AnnotationAwareAspectjAutoProxyCreator对象其实就是这个类型InstantiationAwareBeanPostProcessor,也就是说在这里这个接口的相关方法会被回调,下面看看他的实现类AbstractAutoProxyCreator对这个before()方法的重写实现,源码如下:

    主要逻辑就是找出需要产生代理增强的bean(切面类),和普通的bean, 需要增强的bean放在advisedBeans里面,因为需要增强的bean是需要动态植入其他逻辑的,所以不放在一起

    判断当前bean是否是基础类型的,比如: Advice PointCut Advisor AopInfrastructureBean 或者是 切面Aspectj 都算是基础类型,标注这些信息的类,是不会被增强的,标记false

    主意啊,上面说的都是作用都是进行了一下标记

    //todo 跟进来
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    	Object cacheKey = getCacheKey(beanClass, beanName);
    
    	if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
    		if (this.advisedBeans.containsKey(cacheKey)) {
    			return null;
    		}
    		// todo 亮点就是在这里,  如果是我们切面类来到这里,条件是满足的
    		// todo advicedBeans    见名知意: 通知beans
    		// todo Spring用它标识,  被放在这个方法中的类,全部都不会被增强
    		// todo 满足什么条件时,通过检查呢? 就是检查是否标记有 @Aspectj  @Before ... 等注解
    
    		// todo 说的再直接一点, 就是返回了null, 表示当前的切面仍然需要按照正常的流程创建出来,但是这里进行标记了
    		if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
    			this.advisedBeans.put(cacheKey, Boolean.FALSE);
    			return null;
    		}
    	}
    
    	// Create proxy here if we have a custom TargetSource. todo 如果我们有一个自定义的TargetSource,在这里创建代理
    	// Suppresses unnecessary default instantiation of the target bean: // todo 抑制不必要的目标bean的默认实例化:
    	// The TargetSource will handle target instances in a custom fashion. todo 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;
    }
    

    经过上面的标记,在哪里产生的代理对象呢?其实是在AbstractAutowireCapeableBeanFactory中的initializeBean()方法中实现的postProcessAfterInitialization()实现的,在本文的末尾展开讨论


    第二件大事: 实例化对象, 继续跟进

    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    		throws BeanCreationException {
    
    	if (logger.isDebugEnabled()) {
    		logger.debug("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.
    	// todo 做各种各样的属性值的赋值, 比如这种 通过Spring的Bean传递给Spring框架的值  ==> bd.setPropertyValue("aaa")
    	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    		mbdToUse = new RootBeanDefinition(mbd);
    		mbdToUse.setBeanClass(resolvedClass);
    	}
    
    	// Prepare method overrides.
    	// todo 处理 lookup-method 和 replace-method 配置,Spring 将这两个配置统称为 override method
    	try {
    		mbdToUse.prepareMethodOverrides();
    	}
    	catch (BeanDefinitionValidationException ex) {
    		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
    				beanName, "Validation of method overrides failed", ex);
    	}
    
    	try {
            // todo 在实例化之前完成一次解析操作,这也是
    		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 {
    		//todo 调用 doCreateBean 创建bean
    		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    		if (logger.isDebugEnabled()) {
    			logger.debug("Finished creating instance of bean '" + beanName + "'");
    		}
    		return beanInstance;
    	}
    }
    

    我们继续跟进doCreateBean(beanName, mbdToUse, args);方法, 同样是本类AbstarctAutowireCapableBeanFactory的方法,源码如下: 这个方法也是无与伦比的重要,那这个方法中做了什么事情呢?如下

    • 创建一个 BeanWrapper,用来存放bean+其他属性
    • 创建bean的实例,封装进上面的BeanWrapper中
    • 分两次调用处理处理器
    • 设置属性,填充属性
    • 经过AOP处理,将原生对象转换成Proxy
    • 返回BeanWrapper

    因为这个方法简直太重要了,上面列举的每一点都值得我们仔细分析,我们每一条的分析都写在下面代码的下面

    	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    			throws BeanCreationException {
    
    		// Instantiate the bean.
    		// todo BeanWrapper 用来包装bean
    		BeanWrapper instanceWrapper = null;
    		if (mbd.isSingleton()) {
    			// todo 一开始 factoryBeanInstanceCache 这个map中是没有值的, 所以进入下面的if
    			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    		}
    		if (instanceWrapper == null) {
    
    			instanceWrapper = createBeanInstance(beanName, mbd, args);
    		}
    		// todo !!!!!!!!这里获取出来的对象是原生对象!!!!!!!!!!!!
    		final Object bean = instanceWrapper.getWrappedInstance();
    		Class<?> beanType = instanceWrapper.getWrappedClass();
    		if (beanType != NullBean.class) {
    			mbd.resolvedTargetType = beanType;
    		}
    
    		// Allow post-processors to modify the merged bean definition.
    		synchronized (mbd.postProcessingLock) {
    			if (!mbd.postProcessed) {
    				try {
    	
    					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    				}
    				catch (Throwable ex) {
    					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    							"Post-processing of merged bean definition failed", ex);
    				}
    				mbd.postProcessed = true;
    			}
    		}
    
    		// Eagerly cache singletons to be able to resolve circular references
    		// even when triggered by lifecycle interfaces like BeanFactoryAware.
    		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    				isSingletonCurrentlyInCreation(beanName));
    		if (earlySingletonExposure) {
    			if (logger.isDebugEnabled()) {
    				logger.debug("Eagerly caching bean '" + beanName +
    						"' to allow for resolving potential circular references");
    			}
    
    			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    		}
    
    		// Initialize the bean instance.
    		Object exposedObject = bean; // todo 到目前为止还是原生对象
    	
    			//todo  用来填充属性
    			//设置属性,非常重要
    			populateBean(beanName, mbd, instanceWrapper);
    			
    			// todo 经过AOP处理,原生对象转换成了代理对象,跟进去
    			//执行后置处理器,aop就是在这里完成的处理
    			exposedObject = initializeBean(beanName, exposedObject, mbd);
    	
    		return exposedObject;
    	}
    

    实例化对象

    我把源码贴在了下面,下面方法的目的就是选出一个策略来实例化一个对象, 那有什么策略呢? 这就看程序员是怎么配置的了, 程序员可以配置工厂方法,指定构造方法,或者是程序员没有做出任何干涉,让Spring按自己的方式去实例化

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    		// Make sure bean class is actually resolved at this point.
    		Class<?> beanClass = resolveBeanClass(mbd, beanName);
    
    		/**
    		 * todo 检测一个类的访问权限, Spring默认是 允许访问非public类型的方法
    		 */
    		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
    			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    		}
    
    		/**
    		 *  创建一个bean的快捷方式
    		 */
    		boolean resolved = false;
    		boolean autowireNecessary = false; // todo 是否是必须自动装配
    		if (args == null) {
    			synchronized (mbd.constructorArgumentLock) {
    
    				// todo
    				if (mbd.resolvedConstructorOrFactoryMethod != null) {
    					resolved = true;
    					//如果已经解析了构造方法的参数,则必须要通过一个带参构造方法来实例
    					autowireNecessary = mbd.constructorArgumentsResolved;
    				}
    			}
    		}
    
    		if (resolved) {
    			if (autowireNecessary) {// todo 如果是需要自动注入的,就使用构造方法自动注入
    				// 通过构造方法自动装配的方式构造 bean 对象
    				return autowireConstructor(beanName, mbd, null, null);
    			}
    			else {
    				//通过默认的无参构造方法进行
    				//todo 通过默认的无参构造方法
    				return instantiateBean(beanName, mbd);
    			}
    		}
    
    		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
    				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
    			// todo 使用特定的构造方法完成自动装配
    			return autowireConstructor(beanName, mbd, ctors, args);
    		}
    
    		// No special handling: simply use no-arg constructor.
    		//todo 使用默认的无参构造方法进行初始化
    		return instantiateBean(beanName, mbd);
    	}
    
    

    我们主要关注上面代码的 determineConstructorsFromBeanPostProcessors(beanClass, beanName)这个方法的目的就是推测实例化需要的构造方法, 为什么需要先推测构造方法呢? 因为Spring实例化对象时,需要使用特定的构造方法才能反射出对象,这时如果程序员指定了带参数的构造方法,spring就会使用这个构造方法实例化对象,如果程序员提供了一个不带任何参数的默认构造方法,Spring会忽略它,按自己的逻辑使用默认的无参构造

    所以上面的if-else分支目的很明确,先是尝试获取全部的构造方法,然后看看有没有解析出来构造方法, 解析出来的话,就使用第一种逻辑,按照 特殊的构造方法模式进行处理,有解析出来,就使用默认的构造方法

    我们进一步跟进这个determineConstructorsFromBeanPostProcessors(beanClass, beanName)方法,可以发现方法里面又是一波后置处理器的回调工作,这次选出的后置处理器的类型是SmartInstantiationAwareBeanPostProcessor,见名知意,这种处理器可以感知到心仪的构造方法,它的主要实现逻辑就是,查看这个将被实例化的对象中有没有添加了@Lookup注解的方法,有的话为这种方法生成代理,循环遍历所有的构造方法,看看这些构造方法上存在不存在@Value或者@Autowired注解,因为这些注解中存在required=true,只要存在这种注解,Spring就将他当成候选的构造方法,但是如果存在多个的话,Spring也不知道到底用哪一个,但是在这里Spring会将所有符合条件的都选出来,但是一般情况下,都可以正确的选出合适的构造

    选择出合适构造方法之后,就根据不同的构造方法,选择使用不同的方式去实例化对象, 都有什么方式呢? 两种方式

    方式1:

    这是比较复杂的方式,此时Spring需要在这个方法内存比较好几个候选的构造方法,计算它们的差异值,最终值最小的构造函数就是将要用来实例化对象的构造函数,当然很可能是选不出合适的构造函数的,于是Spring没有立即抛出异常,而是将异常添加进bean工厂的suppressedExceptions这个set集合中

    如果成功的选择出来一个构造函数,就会使用jdk原生的反射机制,实例化一个对象

     autowireConstructor(beanName, mbd, ctors, args);
    

    方式2:

    直接使用JDK原生的反射机制,实例化一个对象

    instantiateBean(beanName, mbd);
    

    小结:

    代码看到这里,方才说的有才华的那个类AbstactAutowiredCapatableBeanFactory中的doCreateBean()方法的 instanceWrapper = createBeanInstance(beanName, mbd, args); 也就看完了, 到这里也就知道了,Spring会先把所有满足条件的bean全部实例化存放起来,这里的对象是百分百原生java对象,不掺水不含糖

    接着往下看,我把代码重写贴出来, 下面还有五件大事,这四件大事说完了,本文就结束了

    第一: 是applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 回调后置处理器,进行有关注解的缓存操作

    第二: 是getEarlyBeanReference(beanName, mbd, bean) 获取一个提早暴露的beanDefinition对象,用于解决循环依赖问题

    第三: 将刚才创建原生java对象存放一个叫singletonFactories的map中,这也是为了解决循环依赖而设计的数据结构,举个例子: 现在准备创建A实例, 然后将A实例添加到这个singletonFactories中, 继续运行发现A实例依赖B实例,于是在创建B实例,接着又发现B实例依赖A实例,于是从singletonFactories取出A实例完成装配,再将B返回给A,完成A的装配

    
    	synchronized (mbd.postProcessingLock) {
    			if (!mbd.postProcessed) {
    				try {
    
    					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    				}
    				catch (Throwable ex) {
    					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    							"Post-processing of merged bean definition failed", ex);
    				}
    				mbd.postProcessed = true;
    			}
    		}
    
    		// Eagerly cache singletons to be able to resolve circular references
    		// even when triggered by lifecycle interfaces like BeanFactoryAware.
    		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    				isSingletonCurrentlyInCreation(beanName));
    		if (earlySingletonExposure) {
    			if (logger.isDebugEnabled()) {
    				logger.debug("Eagerly caching bean '" + beanName +
    						"' to allow for resolving potential circular references");
    			}
    
    			// todo  重点再来看这个 addSingleFactory
    			// todo  将原始对象new出来之后放到了  这个方法中的map中
    			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    		}
    
    		// Initialize the bean instance.
    		Object exposedObject = bean; // todo 到目前为止还是原生对象
    		try {
    			//todo  用来填充属性
    			//设置属性,非常重要
    			populateBean(beanName, mbd, instanceWrapper);
    
    			// todo 经过AOP处理,原生对象转换成了代理对象,跟进去
    			//执行后置处理器,aop就是在这里完成的处理
    			exposedObject = initializeBean(beanName, exposedObject, mbd);
    		}
    

    接着看 populateBean(beanName, mbd, instanceWrapper);方法,这个方法很重要,就是在这个方法中进行bean属性的装配工作,啥意思呢? 比如现在装配A实例,结果发现A实例中存在一个属性是B实例,这是就得完成自动装配的工作,源码如下:

    如果仔细看,就会发现两个事:

    第一: 如果不出意外,就会出现两次后置处理器的回调,第一后置处理器的回调是判断当前的bean中是否存在需要装配的属性,而第二波后置处理器的回调就是实打实的去完成装配的动作

    第二: 下面的第一个处理器其实就是spring启动过程中第一个回调的处理器,只不过调用了这个处理器的不同的方法postProcessAfterInstantiation(),默认返回ture表示按照正常的流程装配对象的属性,返回false,表示不会继续装配对象中的任何属性

    而我们则继续关注下面方法中的第二个后置处理器的,看看Spring是如何完成属性的自动装配的,关于这部分的跟踪,我写在下面代码的后面

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    		if (bw == null) {
    			if (mbd.hasPropertyValues()) {
    				throw new BeanCreationException(
    						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
    			}
    			else {
    				// Skip property population phase for null instance.
    				return;
    			}
    		}
    
    		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    		// state of the bean before properties are set. This can be used, for example,
    		// to support styles of field injection.
    		boolean continueWithPropertyPopulation = true;
    
    		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    				if (bp instanceof InstantiationAwareBeanPostProcessor) {
    					//todo 进行了强转, InstantiationAwareBeanPostProcessor这个接口前面说过
    					// todo 只要是通过这个接口返回出来的bean Spring不在管这个bean,不给他装配任何属性
    					//todo 当前这里没有用它这个变态的特性
    					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    					// todo postProcessAfterInstantiation()默认是返回true, 加上! 表示false
    					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    						continueWithPropertyPopulation = false;
    						break;
    					}
    				}
    			}
    		}
    
    		if (!continueWithPropertyPopulation) {
    			return;
    		}
    		// todo Spring内部可以对BeanDefinition进行设置值, 参照自定义的 BeanFactory中获取到BeanDefinition.getPropertyValue().addXXX();
    		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    
    		// todo 判断当前bean的解析模型是 byName 还是 byType
    		// todo 再次验证了:::   当程序员直接使用@Autowired注解时, 既不是ByName 也不是ByType, 而是No
    		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
    			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    			// Add property values based on autowire by name if applicable.
    			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
    				autowireByName(beanName, mbd, bw, newPvs);
    			}
    			// Add property values based on autowire by type if applicable.
    			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
    				autowireByType(beanName, mbd, bw, newPvs);
    			}
    			pvs = newPvs;
    		}
    
    		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    
    		if (hasInstAwareBpps || needsDepCheck) {
    			if (pvs == null) {
    				pvs = mbd.getPropertyValues();
    			}
    			//todo 获取出对象的所有set get方法,现在是有一个 getClass()方法,因为继承了Object, 没什么其他卵用
    			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    			if (hasInstAwareBpps) {
    
    				for (BeanPostProcessor bp : getBeanPostProcessors()) {
    					if (bp instanceof InstantiationAwareBeanPostProcessor) {
    					
    						pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
    						if (pvs == null) {
    							return;
    						}
    					}
    				}
    			}
    			if (needsDepCheck) {
    				checkDependencies(beanName, mbd, filteredPds, pvs);
    			}
    		}
    
    		if (pvs != null) {
    			applyPropertyValues(beanName, mbd, bw, pvs);
    		}
    	}
    

    好,继续跟进 pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(),,看看spring如何完成属性的自动装配,当然,还是那句话,如果我们直接跟进去这个方法进入的是InstantiationAwareBeanPostProcessor抽象接口抽象方法,而我们关注的是它的实现类AutowiredAnnotationBeanDefinitionPostProcessor的实现,打上断点依次跟进

    	@Override
    	public PropertyValues postProcessPropertyValues(
    			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
    
    		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    		try {
    			// todo 跟进来, 目的是  为 beanName 填充上属性 bean
    			metadata.inject(bean, beanName, pvs);
    

    跟进

    metadata.inject(bean, beanName, pvs);
    

    源码如下:

    可以这样理解,在下面的方法中遍历当前对象中所有可能需要依赖注入的属性字段

    	public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    		// todo 这里的  InjectedElement 表示单个的需要注入的元素对象
    		Collection<InjectedElement> checkedElements = this.checkedElements;
    		Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements);
    		if (!elementsToIterate.isEmpty()) {
    			for (InjectedElement element : elementsToIterate) {
    				if (logger.isDebugEnabled()) {
    					logger.debug("Processing injected element of bean '" + beanName + "': " + element);
    				}
    				//todo 跟进  AutowiredAnnotationBeanPostProcessor 对这个方法的实现, 在600多行处
    				element.inject(target, beanName, pvs);
    			}
    		}
    	}
    

    跟进这个inject() 我是手动删除了这个方法中其他的很多判断,仅仅保存下来了下面我们关注的逻辑,逻辑很清楚,上面的代码中不是在遍历所有需要自动装配的field吗?如果找到了的话,就得完成自动装配,自动装配什么呢? 其实就是自动装配上当前对象依赖的其他的对象而已,因为我们使用的后置处理器是AutowireAnnotationBeanPostProcessor通过下面的代码就能得出结论就是@Autowired默认情况下是通过反射实现的自动装配

    	// todo 来到这里
    		@Override
    		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    			Field field = (Field) this.member;
    			Object value;
    			value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    			if (value != null) {
    				ReflectionUtils.makeAccessible(field);
    				field.set(bean, value);
    			}
    		}
    	}
    

    我们一路往下跟进resolveDependency()我们关注这个方法如下代码:

    if (instanceCandidate instanceof Class) {// todo !!!!!当运行到这行代码时, myService还没有被实例化(singletonObjects中没有) 执行完这一个行代码之后, IndexDao1完成了对myService的装配
    		instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
    	}
    

    跟进这个resolveCandidate()源码如下:

    很直接发现,出现的递归的现象,这其实解析清楚了Spring是如何完成属性注入的,就是只不过前前后后很多接口很多类,会扰乱这个阅读的过程

    public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
    		throws BeansException {
    	// todo 从bean工厂的获取,  beanName = myService   requiredType = com.changwu...OrderService2 , 跟进去这个方法, 他调用了AbstractBeanFactory中的getBean(){ doGetBean();}
    	return beanFactory.getBean(beanName);
    }
    

    完成装配后,其实现在的对象依然是原生的java对象 回到AbstractAutowireCapableBeanFactory中的initializeBean()方法,源码如下, 看了下面的代码就是知道了为什么applyBeanPostProcessorsBeforeInitializationinit()applyBeanPostProcessorsAfterInitialization()之间的调用顺序了

    还有最后一个秘密需要揭开: Spring的AOP不是产生了代理对象? 那什么时候完成的代理呢?毕竟从我开始写这篇文章到最后都没有看到,其实AOP的实现就在下面的代码中

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    	if (System.getSecurityManager() != null) {
    		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    			invokeAwareMethods(beanName, bean);
    			return null;
    		}, getAccessControlContext());
    	}
    	else {
    		invokeAwareMethods(beanName, bean);
    	}
    
    	Object wrappedBean = bean;
    	if (mbd == null || !mbd.isSynthetic()) {
    		//todo 执行全部的后置处理器的 Before方法
    		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    	}
    
    	try {
    		// todo 执行所有的init方法
    		invokeInitMethods(beanName, wrappedBean, mbd);
    	}
    	catch (Throwable ex) {
    		throw new BeanCreationException(
    				(mbd != null ? mbd.getResourceDescription() : null),
    				beanName, "Invocation of init method failed", ex);
    	}
    	if (mbd == null || !mbd.isSynthetic()) {
    		// todo 执行所有的后置处理器的 after方法
    		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    	}
    
    	return wrappedBean;
    }
    

    我们在前面知道当遇到这个AbstractAutoProxyCreator时,回调它的before()方法时,仅仅是标记哪些对象需要进行增强哪些对象不需增强,而没有立即生成代理对象

    现在我们关注这行代码 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); ,生成代理对象的逻辑就在这里面

    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
    	if (bean != null) {
    		Object cacheKey = getCacheKey(bean.getClass(), beanName);
    		if (!this.earlyProxyReferences.contains(cacheKey)) {
    			// todo 进入
    			return wrapIfNecessary(bean, beanName, cacheKey);
    		}
    	}
    	return bean;
    }
    
    

    看这个方法wrapIfNecessary(bean, beanName, cacheKey);最终会进入这个实现中

    大家可以看到Spring为bean生成了代理对象,默认会先检查被代理的对象有没有实现接口,如果实现了接口,就是用jdk动态代理,否则就看看有没有cglib的相关依赖,如果存在的相关依赖而没有实现接口,就会使用cglib的代理模式

    另外,补充通过编码的方式控制 下面的if条件

    • config.isOptimize() -> 可以通过XMl配置, 默认false
    • config.isProxyTargetClass() -> @EnableAspectjAutoPeoxy(true) 默认也是false
    @SuppressWarnings("serial")
    public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    
    	if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
    		Class<?> targetClass = config.getTargetClass();
    		if (targetClass == null) {
    			throw new AopConfigException("TargetSource cannot determine target class: " +
    					"Either an interface or a target is required for proxy creation.");
    		}
    		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
    			//todo 目标对象是一个接口, 同样是使用jdk的动态代理
    			return new JdkDynamicAopProxy(config);
    		}
    		return new ObjenesisCglibAopProxy(config);
    	}
    	else {
    		// todo 所以默认使用的是 jdk的动态代理
    		return new JdkDynamicAopProxy(config);
    	}
    }
    
    
  • 相关阅读:
    108. Convert Sorted Array to Binary Search Tree
    107. Binary Tree Level Order Traversal II
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    104. Maximum Depth of Binary Tree
    103. Binary Tree Zigzag Level Order Traversal
    102. Binary Tree Level Order Traversal
    系统和进程相关信息
    文件I/0缓冲
    系统编程概念(文件系统mount等函数的使用)
  • 原文地址:https://www.cnblogs.com/ZhuChangwu/p/11755973.html
Copyright © 2011-2022 走看看