Анализ исходного кода Spring5 второй

Spring

// Вышеупомянутое для сканирования обычных бобов

//Обработка 3 случаев @Import (обычный класс; класс ImportSelector; класс ImportBeanDefinitionRegistrar) private void processImports (ConfigurationClass configClass, SourceClass currentSourceClass, Коллекция importCandidates, логическое значение checkForCircularImports) { если (importCandidates.isEmpty()) { возвращение; }

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不同。

Для обработки импортированного бина он обрабатывается в методе ConfigurationClassPostProcessor # processConfigBeanDefinitions(), то есть следующий код:

/**

  • Здесь стоит отметить, что сканируемые бины могут содержать специальные классы
  • Например, в этом методе также обрабатывается ImportBeanDefinitionRegistrar.
  • Но не включены в configClasses
  • configClasses в основном содержит importSelector
  • Поскольку ImportBeanDefinitionRegistrar был добавлен в список при сканировании

*/ //bd для отображения, кроме обычного 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());

}

// Зарегистрируйте bean-компоненты, введенные import и importSelector в bean factory private void registerBeanDefinitionForImportedConfigurationClass (ConfigurationClass configClass) { Метаданные AnnotationMetadata = configClass.getMetadata(); AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(метаданные);

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, в фабрику компонентов private void loadBeanDefinitionsFromRegistrars(Map регистраторы) { registrars.forEach((регистратор, метаданные) -> registrar.registerBeanDefinitions(метаданные, 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); если (this.factoriesPostProcessed.contains(factoryId)) { бросить новое исключение IllegalStateException( "postProcessBeanFactory уже вызвал этот постпроцессор против " + beanFactory); } this.factoriesPostProcessed.add(factoryId); если (!this.registriesPostProcessed.contains(factoryId)) { // Хук BeanDefinitionRegistryPostProcessor явно не поддерживается... // Тогда просто лениво вызовите processConfigurationClasses. processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory); } // Генерируем прокси cglib для класса конфигурации //Зачем вам нужно генерировать прокси cglib? (Создайте прокси-класс для AppConfig, а метод configDao2() вызовет метод configDao1()) улучшитьConfigurationClasses (beanFactory); beanFactory.addBeanPostProcessor (новый ImportAwareBeanPostProcessor (beanFactory)); }

public voidEnhanceConfigurationClasses (ConfigurableListableBeanFactory beanFactory) { Map configBeanDefs = new LinkedHashMap(); for (String beanName: beanFactory.getBeanDefinitionNames()) { BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName); //Определяем, является ли это полностью аннотированным классом //Scan — это полностью аннотированный класс? Соотношение между полным и облегченным если (ConfigurationClassUtils.isFullConfigurationClass (beanDef)) { if (!(beanDef instanceof AbstractBeanDefinition)) { выбросить новое исключение BeanDefinitionStoreException (""); } иначе если (logger.isWarnEnabled() && beanFactory.containsSingleton(beanName)) { логгер.предупреждать(""); } configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef); } } если (configBeanDefs.isEmpty()) { возвращение; }

//完成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

Расширение общедоступного класса (Class configClass, @Nullable ClassLoader classLoader) { //Определяем, был ли он проксирован если (EnhancedConfiguration.class.isAssignableFrom(configClass)) { если (logger.isDebugEnabled()) { logger.debug(""); } вернуть класс конфигурации; } //Не проксируется прокси cglib Class> EnhancedClass = createClass(newEnhancer(configClass, classLoader)); если (logger.isDebugEnabled()) { logger.debug(String.format(""); } вернуть расширенный класс; }

private Enhancer newEnhancer (Class configSuperClass, @Nullable ClassLoader classLoader) { Enhancer Enhancer = новый Enhancer(); //Расширяем родительский класс, всем известно, что cglib основан на наследовании Enhancer.setSuperclass (configSuperClass); // Улучшить интерфейс, зачем улучшать интерфейс? //Легко судить, представляет класс и расширяется (реализует BeanFactoryAware, чтобы получить объект BeanFactory) Enhancer.setInterfaces (новый класс [] {EnhancedConfiguration.class}); //Не наследовать интерфейс Factory Enhancer.setUseFactory(false); Enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); // BeanFactoryAwareGeneratorStrategy — стратегия генерации // В основном добавляем переменные-члены $$beanFactory в сгенерированный класс CGLIB // При этом на основе метода setBeanFactory в родительском интерфейсе BeanFactoryAware интерфейса EnhancedConfiguration, // Установите значение этой переменной в beanFactory в текущем контексте, чтобы наш прокси-объект cglib имел beanFactory // С фабрикой вы можете получить объект вместо того, чтобы получать объект через метод, потому что получение объекта через метод не может контролировать процесс // Роль BeanFactory состоит в том, чтобы перехватить вызов, когда он вызывается, и получить целевой компонент непосредственно в beanFactory Enhancer.setStrategy (новый BeanFactoryAwareGeneratorStrategy (classLoader)); //Метод фильтра, нельзя каждый раз переходить на новый Enhancer.setCallbackFilter(CALLBACK_FILTER); Enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes()); усилитель возврата; }

//CALLBACK_FILTER: setCallbackFilter private static final Callback[] CALLBACKS = new Callback[] { //Расширенный метод, в основном для управления областью действия bean-компонента //(без вызова new каждый раз) новый BeanMethodInterceptor(), //Настраиваем beanFactory новый BeanFactoryAwareMethodInterceptor(), NoOp.INSTANCE }; частный статический окончательный ConditionalCallbackFilter CALLBACK_FILTER = новый ConditionalCallbackFilter (CALLBACKS);

/**

  • Используется для перехвата вызовов метода @Bean и получения целевого компонента непосредственно из BeanFactory вместо выполнения метода.

*/ 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)