3、refresh()
继续看AbstractApplicationContext
#refresh()
方法,接上节到3.4
3.4 postProcessBeanFactory(beanFactory)
是个空方法
3.5 invokeBeanFactoryPostProcessors(beanFactory)
Invoke factory processors registered as beans in the context,执行bean工厂后置处理器
下面做简单的测试
//定义个类,通过加注解,然后被扫描到加入到容器中,默认为单例
@Repository
public class UserDao {
}
定义MyBeanFactoryProcesser
,拿到userDao这个bean在工厂中对应的BeanDefinition,通过BeanDefinition可以拿到关于userDao这个bean在Spring容器中的很多信息,这里我们将其设置为多例
@Component
public class MyBeanFactoryProcesser implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userDao");
beanDefinition.setScope("prototype");
}
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
Object dao1 = ac.getBean("userDao");
Object dao2 = ac.getBean("userDao");
System.out.println(dao1);
System.out.println(dao2);
}
}
可以看到此时的UserDao在容器中已经不是单例的了
如果注释掉MyBeanFactoryProcesser
的@Component
注解再次运行后,UserDao又是单例的了。
修改测试方法如下
@Configuration
@ComponentScan("com.liaoxiang")
public class AppConfig {
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.register(AppConfig.class);
ac.addBeanFactoryPostProcessor(new MyBeanFactoryProcesser());
ac.refresh();
Object dao1 = ac.getBean("userDao");
Object dao2 = ac.getBean("userDao");
System.out.println(dao1);
System.out.println(dao2);
}
}
此时UserDao又变成多例的了,加断点看一下,从3.5行所在代码直接进入invokeBeanFactoryPostProcessors()
方法,定义在AbstractApplicationContext
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
* =================================================================================================================!!
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//第二参数getBeanFactoryPostProcessors()获取的自定义的且没有加注解的bean工厂后置处理器
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
可以看到getBeanFactoryPostProcessors()
获取到的就是没有加注解的自定义处理器,beanFactoryPostProcessors
是AbstractApplicationContext
的成员变量:
/** BeanFactoryPostProcessors to apply on refresh */
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
/**
* Return the list of BeanFactoryPostProcessors that will get applied
* to the internal BeanFactory.
*/
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
return this.beanFactoryPostProcessors;
}
当我们在测试方法中执行:
ac.addBeanFactoryPostProcessor(new MyBeanFactoryProcessor())
,实际执行的是AbstractApplicationContext
类中下面的方法:
@Override
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
this.beanFactoryPostProcessors.add(postProcessor);
}
如果我们使用的是加了注解的自定义处理器,交由Spring容器来处理,即上面第一次的情况运行到此处的话,其结果如下,getBeanFactoryPostProcessors()
方法返回为空,因为在整个过程中并没有向beanFactoryPostProcessors
这个List集合中添加任何的处理器
在未加注释的情况下(自己new,手动添加)继续执行,进入到:
PostProcessorRegistrationDelegate
#invokeBeanFactoryPostProcessors()
方法
final class PostProcessorRegistrationDelegate {
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
//这里的beanFactory是DefaultListableBeanFactory对象,它实现了BeanDefinitionRegistry接口
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//存放自定义的BeanFactoryPostProcessor--->MyBeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//BeanDefinitionRegistryPostProcessor已经继承了BeanFactoryPostProcessor接口
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//循环的是自定义的实现了BeanFactoryPostProcessor接口的类的集合,未加注解
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
/**
* 我们定义的处理器处理器实现的是BeanFactoryPostProcessor,所以这个为false
* 当我们定义的处理器实现的接口是BeanDefinitionRegistryPostProcessor时,就会进入这个方法
* 最后会将自定义的处理器加入到registryProcessors中
* BeanDefinitionRegistryPostProcessor接口扩展了BeanFactoryPostProcessor接口
* 扩展方法:
* postProcessBeanDefinitionRegistry
*/
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
// 将自定义的处理器加入到regularPostProcessors
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
// currentRegistryProcessors放的spring内部自己的实现了BeanDefinitionRegistryPostProcessor接口的处理器
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 合并
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
.....
//省略部分代码
两个Bean工厂后置处理器接口,这是spring的两个扩展点,实现这两个接口就可以插手beanFactory的创建过程(上一节中的BeanPostProcessor
也是一个扩展点)
/**
* Allows for custom modification of an application context's bean definitions,
* adapting the bean property values of the context's underlying bean factory.
*
* <p>Application contexts can auto-detect BeanFactoryPostProcessor beans in
* their bean definitions and apply them before any other beans get created.
*
* <p>Useful for custom config files targeted at system administrators that
* override bean properties configured in the application context.
*
* <p>See PropertyResourceConfigurer and its concrete implementations
* for out-of-the-box solutions that address such configuration needs.
*
* <p>A BeanFactoryPostProcessor may interact with and modify bean
* definitions, but never bean instances. Doing so may cause premature bean
* instantiation, violating the container and causing unintended side-effects.
* If bean instance interaction is required, consider implementing
* {@link BeanPostProcessor} instead.
*
* @author Juergen Hoeller
* @since 06.07.2003
* @see BeanPostProcessor
* @see PropertyResourceConfigurer
*/
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
/**
* Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
* the registration of further bean definitions <i>before</i> regular
* BeanFactoryPostProcessor detection kicks in. In particular,
* BeanDefinitionRegistryPostProcessor may register further bean definitions
* which in turn define BeanFactoryPostProcessor instances.
*
* @author Juergen Hoeller
* @since 3.0.1
* @see org.springframework.context.annotation.ConfigurationClassPostProcessor
*/
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
将我们自定义(以后说自定义都是未加注解,自己显示new出来的)后置处理器加到名为regularPostProcessors
的List集合中,(如果自定义的处理器加了注解交由Spring容器实例化,直接跳过for循环)此时for循环执行一次,然后往下执行到beanFactory.getBeanNamesForType()
方法,跟进去,进入到DefaultListableBeanFactory
类中,这个方法的作用是根据一个类型来拿到所有这个类型的类的类名,BeanDefinition中就描述的有类的类型和BeanName等,这里的这个方法就是在beanFactory中找出类型为BeanDefinitionRegistryPostProcessor.class
的所有bean的beanName
// 参数为一个Class 和 两个布尔类型,上面传入的类型并不为null,if判断为true,调用doGetBeanNamesForType
@Override
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
Map<Class<?>, String[]> cache =
(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
String[] resolvedBeanNames = cache.get(type);
if (resolvedBeanNames != null) {
return resolvedBeanNames;
}
resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
最后通过这个方法拿到了ConfigurationClassPostProcessor
的BeanName,ConfigurationClassPostProcessor
这个类是在上一节new AnnotatedBeanDefinitionReader(this)
的时候加入到DefaultListableBeanFactory
类中的beanDefinitionMap
中的,为的就是在spring的beanFactory初始化的过程中去做一些事情,那么到底做哪些事情呢,下面揭晓
for循环执行完成之后
往下执行到invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 合并,如果我们自定义的处理器实现的是BeanDefinitionRegistryPostProcessor接口,就会加入到registryProcessors中
registryProcessors.addAll(currentRegistryProcessors);
// 此时这里传递的参数只有一个,就是ConfigurationClassPostProcessor对象
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
进入PostProcessorRegistrationDelegate
#invokeBeanDefinitionRegistryPostProcessors()
/**
* Invoke the given BeanDefinitionRegistryPostProcessor beans.
* ==================================================================================================================!!
*/
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
/**
* 循环所有的实现了BeanDefinitionRegistryPostProcessor接口的处理器
* 执行处理器中重写的postProcessBeanDefinitionRegistry()方法
*/
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
// 循环postProcessors这个List集合,里面就是ConfigurationClassPostProcessor
// ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor接口
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
进入ConfigurationClassPostProcessor
#postProcessBeanDefinitionRegistry
到这里就开始执行Bean工厂后置处理器的方法了,这是spring自己的后置处理器,如果我们自己也写了一个后置处理器并且实现的是BeanDefinitionRegistryPostProcessor
接口,那么也会在上面的循环中被执行
/**
* Derive further bean definitions from the configuration classes in the registry.
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
进入ConfigurationClassPostProcessor
#processConfigBeanDefinitions()
根据名称拿出工厂中的已存在的所有bd,检查这些bd所描述的类都加有哪些注解
进入ConfigurationClassUtils
#checkConfigurationClassCandidate()
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
// 获取className
String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
AnnotationMetadata metadata;
/**
* 是AnnotatedBeanDefinition类型
* 判断className和元数据里的className
*/
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
// Can reuse the pre-parsed metadata from the given BeanDefinition...
// 获得注解原数据
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
// 是AbstractBeanDefinition类型
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
// Check already loaded Class if present...
// since we possibly can't even load the class file for this Class.
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
// 获得注解原数据
metadata = new StandardAnnotationMetadata(beanClass, true);
}
// 不是上面的两种,从metadataReaderFactory中获取
else {
try {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
// 获得注解原数据
metadata = metadataReader.getAnnotationMetadata();
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex);
}
return false;
}
}
// 通过元数据判断是否加了 @Configuration注解
if (isFullConfigurationCandidate(metadata)) {
// 如果加了就设置FULL属性
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
// 判断是否加了其他四种注解
else if (isLiteConfigurationCandidate(metadata)) {
// 如果加了就设置FULL属性
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
// It's a full or lite configuration candidate... Let's determine the order value, if any.
Integer order = getOrder(metadata);
if (order != null) {
//设置order
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
}
isFullConfigurationCandidate(metadata)
/**
* Check the given metadata for a full configuration class candidate
* (i.e. a class annotated with {@code @Configuration}).
* @param metadata the metadata of the annotated class
* @return {@code true} if the given class is to be processed as a full
* configuration class, including cross-method call interception
*/
public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
return metadata.isAnnotated(Configuration.class.getName());
}
isLiteConfigurationCandidate(metadata)
public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) {
// Do not consider an interface or an annotation...
if (metadata.isInterface()) {
return false;
}
// Any of the typical annotations found?
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
// Finally, let's look for @Bean methods...
try {
return metadata.hasAnnotatedMethods(Bean.class.getName());
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
}
return false;
}
}
是否被这四个注解注释
我们这里单独看一下自己写的加了注释的AppConfig类
对于AppConfig来说由于加了@Configuration
注解,进入isFullConfigurationCandidate
判断后,不会进入直isLiteConfigurationCandidate
判断,而其他类由于没有@Configuration
这个注解会进入isLiteConfigurationCandidate(metadata)
方法,在有@Configuration
注解的时候,spring会自动检查除了这个注解外是否还有其他注解
当有Order注解的时候,设置一下order属性后就返回到ConfigurationClassPostProcessor
类继续执行。
对于检查过后返回true的BD,会构建一个BeanDefinitionHolder
对象,放到一个List集合中:
List<BeanDefinitionHolder> configCandidates
进入ConfigurationClassParser
#parse()
方法,将configCandidates
传过去
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<>();
// 循环set集合,拿出bd
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
// 判断bd是否是被加了注解的bd
if (bd instanceof AnnotatedBeanDefinition) {
// 调用重载的方法
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
processDeferredImportSelectors();
}
进入ConfigurationClassParser
#parse()
,将类信息封装成一个ConfigurationClass
对象,作为参数
进入ConfigurationClassParser
#processConfigurationClass()
进入ConfigurationClassParser
#doProcessConfigurationClass()
,在这个方法中,就在处理各种注解
// Recursively process any member (nested) classes first,处理内部类
// Process any @PropertySource annotations,处理 @PropertySource注解
// Process any @ComponentScan annotations,处理 @ComponentScan注解
// Process any @Import annotations, 处理 @Import 注解
// Process any @ImportResource annotations,处理 @ImportResource注解
// Process individual @Bean methods,处理单个@Bean方法
// Process superclass, if any 处理父类
方法如下:
/**
* Apply processing and build a complete {@link ConfigurationClass} by reading the
* annotations, members and methods from the source class. This method can be called
* multiple times as relevant sources are discovered.
* @param configClass the configuration class being build
* @param sourceClass a source class
* @return the superclass, or {@code null} if none found or previously processed
*/
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// Recursively process any member (nested) classes first,处理内部类
processMemberClasses(configClass, sourceClass);
// Process any @PropertySource annotations,处理 @PropertySource注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// Process any @ComponentScan annotations,处理 @ComponentScan注解
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
//循环解析 @ComponentScan注解中的属性值
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
//检查已扫描的定义集以获得更多的配置类,并在需要时进行递归解析
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations, 处理 @Import 注解
processImports(configClass, sourceClass, getImports(sourceClass), true);
// Process any @ImportResource annotations,处理 @ImportResource注解
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods,处理单个@Bean方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// Process superclass, if any 处理父类
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
到此处,这一节下面都是讲处理 @ComponentScan
注解!!
运行到下面断点处
进入ComponentScanAnnotationParser
#parse()
方法,进行一系列操作之后调用doScan()
进入ClassPathBeanDefinitionScanner
#doScan()
进入ClassPathScanningCandidateComponentProvider
#findCandidateComponents
进入ClassPathScanningCandidateComponentProvider
#scanCandidateComponents
由于此时在com.liaoxiang包下只是给userDao加了@Repository
注解,所以在这里被扫描到,途中变量的信息如下
最后返回bd集合candidates
回到ClassPathBeanDefinitionScanner
#doScan()
方法,进行其他一系列操作之后进入标识的方法中
调用本类中的方法,看到这些参数我们大概就能想到要干嘛了
进入BeanDefinitionReaderUtils
#registerBeanDefinition()
看这个断点的条件就是我们上一节中调试的时候留下的,这是要向工厂中注册bd了!
果然进入到DefaultListableBeanFactory
#registerBeanDefinition()
执行到这里UserDao
就被加入到了beanDefinitionMap
执行完之后,返回ClassPathBeanDefinitionScanner
#doScan()
回到ConfigurationClassParser
#doProcessConfigurationClass()
执行完之后处理@Import
注解,见下一节