likes
comments
collection
share

Spring5源码解析二

作者站长头像
站长
· 阅读数 17

//上面的是扫描普通的bean

//处理@Import的3种情况(正常类;ImportSelector类;ImportBeanDefinitionRegistrar类) private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection importCandidates, boolean checkForCircularImports) { if (importCandidates.isEmpty()) { return; }

if (checkForCircularImports && isChainedImportOnStack(configClass)) {
	this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
	this.importStack.push(configClass);
	try {
		for (SourceClass candidate : importCandidates) {
			if (candidate.isAssignable(ImportSelector.class)) {
				// Candidate class is an ImportSelector -> delegate to it to determine imports
				Class<?> candidateClass = candidate.loadClass();
				//反射实现一个对象
				ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
				ParserStrategyUtils.invokeAwareMethods(
						selector, this.environment, this.resourceLoader, this.registry);
				if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
					this.deferredImportSelectors.add(
							new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
				}
				else {
					//回调
					String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
					Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
					//递归,这里第二次调用processImports
					//如果是一个普通类,会斤else
					processImports(configClass, currentSourceClass, importSourceClasses, false);
				}
			}
			else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
				// Candidate class is an ImportBeanDefinitionRegistrar ->
				// delegate to it to register additional bean definitions
				Class<?> candidateClass = candidate.loadClass();
				ImportBeanDefinitionRegistrar registrar =
						BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
				ParserStrategyUtils.invokeAwareMethods(
						registrar, this.environment, this.resourceLoader, this.registry);
				//添加到一个list当中和importselector不同
				configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
			}
			else {
				// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
				// process it as an @Configuration class
				// 否则,加入到importStack后调用processConfigurationClass 进行处理
				//processConfigurationClass里面主要就是把类放到configurationClasses
				//configurationClasses是一个集合,会在后面拿出来解析成bd继而注册
				//可以看到普通类在扫描出来的时候就被注册了
				//如果是importSelector,会先放到configurationClasses后面进行出来注册
				this.importStack.registerImport(
						currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
				processConfigurationClass(candidate.asConfigClass(configClass));
			}
		}
	}
	catch (BeanDefinitionStoreException ex) {
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanDefinitionStoreException(
				"Failed to process imports candidates for configuration class [" +
				configClass.getMetadata().getClassName() + "]", ex);
	}
	finally {
		this.importStack.pop();
	}
}

}


>processImports,处理import的类,主要是处理3种。
>1. 普通的bean
>2. 实现了 importSelector的bean(可以注册多个类的String数组字符串)
>3. 实现了ImportBeanDefinitionRegistrar

>1. import普通的bean,会先加入到importStack后调用processConfigurationClass 进行处理,放入到configurationClasses后面进行出来注册。
>2. import的是importSelector,会先实例化这个ImportSelector 类,然后执行该selector的selectImports方法,获取要注入到spring的bean工厂的类数组字符串,然后 对该String[]数组,进行再一次调用processImports方法处理,最终都是会进入到import普通bean的步骤,即:会先加入到importStack后调用processConfigurationClass 进行处理,放入到configurationClasses后面进行出来注册。
>3. import的是ImportBeanDefinitionRegistrar,会先实例化这个ImportBeanDefinitionRegistrar类,然后将它添加到一个list当中和importselector不同。

对于import的bean处理,是在 ConfigurationClassPostProcessor # processConfigBeanDefinitions()方法处理,即下面代码:

/**

  • 这里值得注意的是扫描出来的bean当中可能包含了特殊类
  • 比如ImportBeanDefinitionRegistrar那么也在这个方法里面处理
  • 但是并不是包含在configClasses当中
  • configClasses当中主要包含的是importSelector
  • 因为ImportBeanDefinitionRegistrar在扫描出来的时候已经被添加到一个list当中去了 */ //bd 到 map 除却普通 this.reader.loadBeanDefinitions(configClasses);

//ConfigurationClassBeanDefinitionReader public void loadBeanDefinitions(Set configurationModel) { TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator(); for (ConfigurationClass configClass : configurationModel) { loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); } }

private void loadBeanDefinitionsForConfigurationClass( ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

if (trackedConditionEvaluator.shouldSkip(configClass)) {
	String beanName = configClass.getBeanName();
	if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
		this.registry.removeBeanDefinition(beanName);
	}
	this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
	return;
}

//如果一个类是被import的,会被spring标准
//早这里完成注册
if (configClass.isImported()) {
	registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//@Bean
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
	loadBeanDefinitionsForBeanMethod(beanMethod);
}

 //xml
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());

//注册Registrar
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());

}

//将import和importSelector注入的bean,注册到bean工厂中 private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) { AnnotationMetadata metadata = configClass.getMetadata(); AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);

ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);

if (logger.isDebugEnabled()) {
	logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
}

}

//将ImportBeanDefinitionRegistrar注入的bean,注册到bean工厂中 private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) { registrars.forEach((registrar, metadata) -> registrar.registerBeanDefinitions(metadata, this.registry)); }

> 总结:spring扫描类分了4种情况
> 1. 普通类,扫描到即刻注册到beanDefinitionMap中。
> 2. import(普通类),扫描到先存放到configurationClasses一个map集合。
> 3. import(importSelector),扫描到遍历循环一个一个的放到configurationClasses一个map集合。
> 4. import(importBeanDefinitionRegistrar),扫描到之后存放到importBeanDefinitionRegistrars一个map集合中。
> 备注:对于import的类,spring是在扫描之后,调用了loadBeanDefinitions方法将扫描到import的类注册到beanDefinitionMap中。

> full和lite的主要作用:
> 1. 当一个bean加了@Configuration注解,即是full全注解类。
> 2. 当一个bean加了@Component、@ComponentScan、@Import、@ImportResource等注解,即是lite
>备注:full全注解类,spring会为该类生成一个cglib代理类。

> 对于加了@Configuration注解的类,spring会对该类使用cglib产生一个代理类。
> 为什么需要使用cglib代理?
> > AppConfig类,使用@Bean注入了两个bean,在configDao2()方法中调用了configDao1()方法,这里就是为了防止configDao1对象被创建两次的问题。
> 
> 备注:cglib是基于继承的。
> 是在invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);方法执行的。

private static void invokeBeanFactoryPostProcessors( Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) { //因为只有一条数据ConfigurationClassPostProcessor for (BeanFactoryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanFactory(beanFactory); } }

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { int factoryId = System.identityHashCode(beanFactory); if (this.factoriesPostProcessed.contains(factoryId)) { throw new IllegalStateException( "postProcessBeanFactory already called on this post-processor against " + beanFactory); } this.factoriesPostProcessed.add(factoryId); if (!this.registriesPostProcessed.contains(factoryId)) { // BeanDefinitionRegistryPostProcessor hook apparently not supported... // Simply call processConfigurationClasses lazily at this point then. processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory); } //给配置类产生cglib代理 //为什么需要产生cglib代理?(给AppConfig产生代理类,configDao2()方法调用了configDao1()方法) enhanceConfigurationClasses(beanFactory); beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory)); }

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) { Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>(); for (String beanName : beanFactory.getBeanDefinitionNames()) { BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName); //判断是否是一个全注解类 //扫描是全注解类?full和lite的关系 if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) { if (!(beanDef instanceof AbstractBeanDefinition)) { throw new BeanDefinitionStoreException(""); } else if (logger.isWarnEnabled() && beanFactory.containsSingleton(beanName)) { logger.warn(""); } configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef); } } if (configBeanDefs.isEmpty()) { return; }

//完成cglib代理
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
	AbstractBeanDefinition beanDef = entry.getValue();
	// If a @Configuration class gets proxied, always proxy the target class
	beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
	try {
		// Set enhanced subclass of the user-specified bean class
		Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
		if (configClass != null) {
			//完成对全注解类的cglib代理
			Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
			if (configClass != enhancedClass) {
				if (logger.isDebugEnabled()) {
					logger.debug(""));
				}
				beanDef.setBeanClass(enhancedClass);
			}
		}
	}
}

}

ConfigurationClassEnhancer

public Class enhance(Class configClass, @Nullable ClassLoader classLoader) { //判断是否被代理过 if (EnhancedConfiguration.class.isAssignableFrom(configClass)) { if (logger.isDebugEnabled()) { logger.debug(""); } return configClass; } //没有被代理cglib代理 Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader)); if (logger.isDebugEnabled()) { logger.debug(String.format(""); } return enhancedClass; }

private Enhancer newEnhancer(Class configSuperClass, @Nullable ClassLoader classLoader) { Enhancer enhancer = new Enhancer(); //增强父类,地球人都知道cglib是基于继承来的 enhancer.setSuperclass(configSuperClass); //增强接口,为什么要增强接口? //便于判断,表示一个类以及被增强了(实现BeanFactoryAware,为了获得BeanFactory对象) enhancer.setInterfaces(new Class[] {EnhancedConfiguration.class}); //不继承Factory接口 enhancer.setUseFactory(false); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); // BeanFactoryAwareGeneratorStrategy是一个生成策略 // 主要为生成的CGLIB类中添加成员变量$$beanFactory // 同时基于接口EnhancedConfiguration的父接口BeanFactoryAware中的setBeanFactory方法, // 设置此变量的值为当前Context中的beanFactory,这样一来我们这个cglib代理的对象就有了beanFactory // 有了factory就能获得对象,而不用去通过方法获得对象了,因为通过方法获得对象不能控制器过程 // 该BeanFactory的作用是在this调用时拦截该调用,并直接在beanFactory中获得目标bean enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader)); //过滤方法,不能每次都去new enhancer.setCallbackFilter(CALLBACK_FILTER); enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes()); return enhancer; }

//CALLBACK_FILTER:setCallbackFilter private static final Callback[] CALLBACKS = new Callback[] { //增强方法,主要控制bean的作用域 //(不用每一次都去调用new) new BeanMethodInterceptor(), //设置一个beanFactory new BeanFactoryAwareMethodInterceptor(), NoOp.INSTANCE }; private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);

/**

  • 用于拦截@Bean方法的调用,并直接从BeanFactory中获取目标bean,而不是通过执行方法。 */ private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {

    @Override @Nullable public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs, MethodProxy cglibMethodProxy) throws Throwable {

      // enhancedConfigInstance 代理
      // 通过enhancedConfigInstance中cglib生成的成员变量$$beanFactory获得beanFactory。
      ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
    
      String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
    
      // Determine whether this bean is a scoped-proxy
      Scope scope = AnnotatedElementUtils.findMergedAnnotation(beanMethod, Scope.class);
      if (scope != null && scope.proxyMode() != ScopedProxyMode.NO) {
      	String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
      	if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
      		beanName = scopedBeanName;
      	}
      }
      
      if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
      		factoryContainsBean(beanFactory, beanName)) {
      	Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
      	if (factoryBean instanceof ScopedProxyFactoryBean) {
      		// Scoped proxy factory beans are a special case and should not be further proxied
      	}
      	else {
      		// It is a candidate FactoryBean - go ahead with enhancement
      		return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
      	}
      }
    
      //一个非常牛逼的判断
      //判断到底是new 还是get
      //判断执行的方法和调用方法是不是同一个方法
      if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
      	//如果是同一个方法:调用代理对象的方法,执行被代理类的方法(即configDao1()的new ConfigDao1()实例化configDao1对象)
      	return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
      }
      //不是同一个方法:调用getBean方法。(即在执行configDao2()方法,调用了configDao1()方法)
      return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
    

    }

    private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs, ConfigurableBeanFactory beanFactory, String beanName) { //判断他是否正在创建 boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName); try { if (alreadyInCreation) { beanFactory.setCurrentlyInCreation(beanName, false); } boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs); if (useArgs && beanFactory.isSingleton(beanName)) { for (Object arg : beanMethodArgs) { if (arg == null) { useArgs = false; break; } } } //beanFactory.getBean //这个方法spring就写的非常牛逼,在bean实例化的会重点解析 Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) : beanFactory.getBean(beanName)); if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) { if (beanInstance.equals(null)) { if (logger.isDebugEnabled()) { logger.debug("")); } beanInstance = null; } else { String msg = ""; try { BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName); msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription(); } catch (NoSuchBeanDefinitionException ex) { // Ignore - simply no detailed message then. } throw new IllegalStateException(msg); } } Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod(); if (currentlyInvoked != null) { String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked); beanFactory.registerDependentBean(beanName, outerBeanName); } return beanInstance; } finally { if (alreadyInCreation) { beanFactory.setCurrentlyInCreation(beanName, true); } }

      //判断执行的方法和调用方法是不是同一个方法
      private boolean isCurrentlyInvokedFactoryMethod(Method method) {
      	Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
      	return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
      			Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
      }
    

    } }

> 这里给加了@Configuration注解的类使用cglib动态代理产生的代理类:
>1. 主要是使用BeanMethodInterceptor类,在bean被实例化的时候,进行拦截。
>2. 怎么做到在configDao2()方法中调用了configDao1(),而configDao1没有被创建两次?
>>  主要是判断执行的方法和调用方法是不是同一个方法,即在执行configDao2()方法的时候,调用了configDao1()方法。
>>  所以在再次执行configDao1()方法时候,判断出发起调用的主方法是configDao2,即执行方法和调用方法不是同一方法。
>
>3.1 如果是同一个方法:调用代理对象的方法,执行被代理类的方法
>>	   cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
>3.2 不是同一个方法:调用getBean方法
>>      return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
### spring初始化总结
#### spring的扩展点(5个)
>1. BeanPostProcessor
>>插手bean的实例过程、实例化之后,在bean没有被spring的bean容器管理之前干活。
>>经典场景:@PostConstruct、aop 
>2. BeanFactoryPostProcessor
>>spring的bean容器当中任意的一个bean被new出来之前执行,针对beanFactory来建设。
>>经典场景:ConfigurationClassPostProcessor#postProcessBeanFactory,针对配置类(@Configuration注解)加上cglib代理。
>3. BeanFactoryRegistryPostProcessor
>>是BeanFactoryPostProcessor的子类,在BeanFactoryPostProcessor之前执行?因为源码当中先遍历BeanFactoryRegistryPostProcessor(有spring提供的,还有自定义)自定义的先执行。
>>经典场景:ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry,扫描、3种import的扫描、@Bean的扫描,判断配置类是否是一个完整的配置类
>4. ImportSelector
>>通过这个方法selectImports返回一个类名(全名)数组,把他变成beanDefinition,动态添加beanDefinition(这个BeanDefinition是写死的,因为这个BeanDefinition是有spring内部生成的,我们无法改变这些BeanDefinition)
>5. ImportBeanDefinitionRegistrar
>>registerBeanDefinitions方法可以得到BeanDefinitionRegistry故而可以动态添加BeanDefinition,还可以改变BeanDefinition。
>>经典场景:mybatis的mapperScan

#### spring bean初始化结构图:
* ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190911160302476.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI0MTAxMzU3,size_16,color_FFFFFF,t_70)