// Вышеупомянутое для сканирования обычных бобов
//Обработка 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
> 总结: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
//完成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)