属性configurationClass的值是full. 只有full版配置才会创建cglib代理
那么有下面几个问题:
问题1: full版本配置是什么呢?
我们使用@Configuration注解了,就会将configurationClass属性设置为full.当设置为full以后,就会创建一个cglib动态代理.
问题2: 为什么要创建动态代理呢?
动态代理可以保证,每次创建的bean对象只有一个
问题3:那么加@Configuration和不加本质上的区别是什么?
当在配置类中一个@Bean使用方法的方式引入另一个Bean的时候,就会重复加载Bean.如果加了@Configuration,存在则直接使用.
问题4:full是怎么来的呢?
这是在上面调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry);接口的时候,标记的是full还是Lite
下面来看一下源码

在这里一步,执行的时候,进行了这个类是full的还是lite,继续忘下看

此时满足条件的postProcessor只有一个,那就是ConfigurationClassPostProcessor. 下面直接看ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()方法

前面都是一些条件判断,重点看processConfigBeanDefinitions(registry);

在这里,这个方法判断了,这个类是full的还是lite的. 下面直接上代码
@H_
502_49@
*
* Check whether the given bean definition is a candidate for a configuration class
* (or a nested component class declared within a configuration/component class,* to be auto-registered as well),and mark it accordingly.
* @param beanDef the bean definition to check
* @param MetadataReaderFactory the current factory in use by the caller
* @return whether the candidate qualifies as (any kind of) configuration class
static boolean checkConfigurationClassCandidate(
BeanDefinition beanDef,MetadataReaderFactory MetadataReaderFactory) {
String className =
beanDef.getBeanClassName();
if (className ==
null || beanDef.getFactoryMethodName() !=
return ;
}
AnnotationMetadata Metadata;
获取元数据
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
Can reuse the pre-parsed Metadata from the given BeanDefinition...
Metadata =
((AnnotatedBeanDefinition) beanDef).getMetadata();
}
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();
if (
beanfactoryPostProcessor.
class.isAssignableFrom(beanClass) ||
BeanPostProcessor.
AopInfrastructureBean.
EventListenerFactory..isAssignableFrom(beanClass)) {
;
}
Metadata =
AnnotationMetadata.introspect(beanClass);
}
{
MetadataReader MetadataReader =
MetadataReaderFactory.getMetadataReader(className);
Metadata =
MetadataReader.getAnnotationMetadata();
}
(IOException ex) {
Could not find class file for introspecting configuration annotations:
className,ex);
}
;
}
}
判断元数据中是否包含Configuration注解
Map<String,Object> config =
Metadata.getAnnotationAttributes(Configuration.
.getName());
/**
* 判断,proxyBeanMethods属性是否为true,如果为true就是一个完全的类,* 也就是带有@Configuration注解,设置Configuration_class属性为full
*
* proxyBeanMethods配置类是用来指定@Bean注解标注的方法是否使用代理,
* 默认是true使用代理,直接从IOC容器之中取得对象;
* 如果设置为false,也就是不使用注解,每次调用@Bean标注的方法获取到的对象和IOC容器中的都不一样,是一个新的对象,所以我们可以将此属性设置为false来提高性能。
*/
if (config !=
null && !Boolean.FALSE.equals(config.
get(
proxyBeanMethods))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE,CONFIGURATION_CLASS_FULL);
}
// 判断是不是带了@Component,@ComponentScan @Import @ImportResource @Bean注解,// 如果带有这几种注解,就将其Configuration_class属性为lite类型的配置类
isConfigurationCandidate(Metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE,CONFIGURATION_CLASS_LITE);
}
It's a full or lite configuration candidate... Let's determine the order value,if any.
Integer order =
getOrder(Metadata);
if (order !=
) {
beanDef.setAttribute(ORDER_ATTRIBUTE,order);
}
;
}
上面主要是获取元数据,然后判断元数据中是否有Configuration注解. 如果有,返回其属性. 我们判断其属性中proxyBeanMethods是否true,如果是true,那么将其设置为full.
如果配置中带有@Component,@ComponentScan @Import @ImportResource @Bean这几种属性之一,那么就将其设置为lite.
问题5: cglib动态代理做了什么事情呢?
不看源码的情况下,简单可以理解为,去ioc工厂里面通过getBean("car") 查询了看ioc中是否有这个对象,如果有就取出来,不再另创建.
这也是@Configuration 和其他注解类似@Component和@ComponentScan的本质区别:
当在配置类中一个@Bean使用方法的方式引入另一个Bean的时候,就会重复创建Bean
如果加了@Configuration,存在则直接使用.
下面来看个例子
@H_
502_49@
基础类:
Car {
private String name;
Tank tank;
String getName() {
name;
}
setName(String name) {
this.name =
Tank getTank() {
tank;
}
setTank(Tank tank) {
this.tank =
tank;
}
}
Tank {
String name;
Tank() {
System.out.println(创建一个tank);
}
name;
}
}
这是定义的car和tank的基础类
@H_
502_49@
@Configuration
@ComponentScan(basePackages = {
MainConfig {
@Bean("car")
Car car() {
Car car =
Car();
car.setName(zhangsan);
这里调用了Tank类,tank是通过@Bean注解注入的.
car.setTank(tank());
car;
}
@Bean
Tank tank() {
Tank();
}
}
当配置类使用了@Configuration注解的时候,运行main方法
@H_
502_49@
);
context.scan(package);
Car car2 = (Car) context.getBean(
.println(car.getName());
context.close();
}
}

当去掉@Configuration注解的时候,再次运行,我们看到创建了两次tank
@H_
502_49@
//@Configuration
@ComponentScan(basePackages = {
MainConfig {
@Bean()
car.setTank(tank());
car;
}
@Bean
new Tank();
}
}

在main方法中调用了两次(Car) context.getBean("car");
在new一个对象的时候,如果不取ioc容器中取,那么每一次都会创建一个新的.
在ioc容器中,car对象只有一个,但是在构建car的时候,调用了tank,tank在ioc容器中却不一定只有一份. 只有使用了@Configuration,表示需要使用cglib动态代理查找tank类,保证ioc容器中只有一份.
7. 详细研究四次调用中的第一次调用. 通过分析跟踪@ComponentScan注解是如何解析的,
通过跟踪@ComponentScan注解是如何解析的, 分来理解BeanDefinitionScan,BeanDefinitionRegistry,BeanDefinitionReader是如何工作的.
@H_
502_49@
invokebeanfactoryPostProcessors(
ConfigurableListable
beanfactory beanfactory,
调用BeanDefinitionRegistryPostProcessors 的后置处理器
* 定义已处理的后置处理器
();
调用beanfactory.getBean实例化配置类的后置处理器(创世界的类ppName),也就是初始化,实例化,赋值属性.
currentRegistryProcessors.add(
beanfactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors,清空currentRegistryProcessors
currentRegistryProcessors.clear();
这里也有两大步
第一步: 初始化bean工厂的后置处理器
通过调用beanfactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class) 初始化了bean工厂的后置处理器,
第二步: 解析配置
调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry);调用beanDefinitionRegistry的后置处理器. 筛选出符合条件的配置类.

如上图所示,最后筛选出的配置类只有MainConfig配置类. 也就是说configCandidates配置候选集合中只有一个MainConfig
@H_
502_49@
// 创建一个ConfigurationClassParser对象,解析@Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.MetadataReaderFactory,this.problemReporter,this.environment,this.resourceLoader,this.componentScanBeanNameGenerator,registry);
Set<BeanDefinitionHolder> candidates =
new LinkedHashSet<>
(configCandidates);
Set<ConfigurationClass> alreadyParsed =
(configCandidates.size());
do {
// 执行解析
parser.parse(candidates);
parser.validate();
然后,接下来创建了一个对象ConfigurationClassParser,这是一个配置类解析器. 下面将使用这个解析器解析配置类.
重点是如何解析的,代码已重点标注出来了.
@H_
502_49@
// 执行解析
parser.parse(candidates);
我们这里是通过注解解析的,所以直接看下面的代码
@H_
502_49@
void parse(Set<BeanDefinitionHolder>
configCandidates) {
循环配置类
(BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd =
holder.getBeanDefinition();
真正的解析bean定义:通过注解元数据解析
(bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(),holder.getBeanName());
}
......
}
解析主要做了几件事呢?如下图:

解析配置类,看看配置类是否含有如上标记的注解,如果有,则调用响应的返回对其进行解析,处理.
下面来看看源码. 是如何处理这一块的.
@H_
502_49@
*
* 在这里会解析@Component @PropertySources @ComponentScan @ImportResource
* @param configClass
* @param sourceClass
* @param filter
* @return
* @throws IOException
@Nullable
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass,SourceClass sourceClass,Predicate<String>
filter)
throws IOException {
// 1. 处理@Component注解,判断元数据是否带有Component注解
if (configClass.get
Metadata().isAnnotated(Component.
.getName())) {
Recursively process any member (nested) classes first
processMemberClasses(configClass,sourceClass,filter);
}
Process any @PropertySource annotations
// 2. 处理@PropertySource 注解,判断元数据是否带有@PropertySource注解
(AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(),PropertySources.)) {
.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
{
logger.info(Ignoring @PropertySource annotation on [" + sourceClass.get
Metadata().getClassName() +
]. Reason: Environment must implement ConfigurableEnvironment);
}
}
Process any @ComponentScan annotations
3. 处理@ComponentScan注解,判断元数据是否带有@ComponentScan注解
*
* 这里mainConfig配置类中有两个注解,一个是@Configuration,一个是@ComponentScan. 在这里,我们看一下@ComponentScan
componentScans 拿到的就是ComponentScan注解里的属性
Set<AnnotationAttributes> componentScans =
AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(),ComponentScans.if (!componentScans.isEmpty() &&
!
.conditionEvaluator.shouldSkip(sourceClass.getMetadata(),ConfigurationPhase.REGISTER_BEAN)) {
(AnnotationAttributes componentScan : componentScans) {
The config class is annotated with @ComponentScan -> perform the scan immediately
解析扫描出来的类,将其解析为BeanDefinitionHolder对象,并放入到scannedBeanDefinitions中
这正的解析ComponentScans和ComponentScan中的配置
Set<BeanDefinitionHolder> scannedBeanDefinitions =
.componentScanParser.parse(componentScan,sourceClass.getMetadata().getClassName());
循环处理包扫描出来的bean定义
Check the set of scanned definitions for any further config classes and parse recursively if needed
(BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand =
holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand ==
) {
bdCand =
holder.getBeanDefinition();
}
判断当前扫描出来的是不是一个配置类,如果是的话,直接进行递归解析.
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand,1)">.
MetadataReaderFactory)) {
parse(bdCand.getBeanClassName(),holder.getBeanName());
}
}
}
}
// 4. 处理@Import注解
Process any @Import annotations
processImports(configClass,getImports(sourceClass),filter,1)">);
// 5. 处理@ImportResource注解
Process any @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(),ImportResource.if (importResource !=
) {
String[] resources = importResource.getStringArray(
locations);
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass(
reader (String resource : resources) {
String resolvedResource =
.environment.resolverequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource,readerClass);
}
}
// 6. 处理@Bean注解
Process individual @Bean methods
Set<Method
Metadata> beanMethods =
retrieveBeanMethodMetadata(sourceClass);
(MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod( BeanMethod(methodMetadata,configClass));
}
处理默认方法
Process default methods on interfaces
processInterfaces(configClass,sourceClass);
处理超类
Process superclass,if any
(sourceClass.getMetadata().hasSuperClass()) {
String superclass =
sourceClass.getMetadata().getSuperClassName();
if (superclass !=
null && !superclass.startsWith(
java") &&
!
.knownSuperclasses.containsKey(superclass)) {
.knownSuperclasses.put(superclass,configClass);
Superclass found,return its annotation Metadata and recurse
sourceClass.getSuperClass();
}
}
No superclass -> processing is complete
;
}
下面我们重点看对@ComponentScan和@ComponentScans注解的解析,为什么看他呢? 因为很多注解都标记了@Component注解.
比如@Service注解,本身使用@Component

再来看@Controller注解,其实质也是一个@Component注解

我们在自定义配置类的时候,会使用@ComponentScan注解. 并传递一个包,作为扫描包. 如MainConfig配置

这就会扫描包下所有的配置类.
它主要的逻辑如下:

在拿到@ComponentScan注解以后,会对其进行parse. 主要解析里面的注解. 并对每一个注解进行处理. 处理后将其添加到scanner属性中. 最后调用scanner.doScan(....)方法.
源码如下:
@H_
502_49@
解析配置
public Set<BeanDefinitionHolder>
parse(AnnotationAttributes componentScan,final String declaringClass) {
// 定义了一个类路径扫描器ClassPathBeanDefinitionScanner
这里的scanner用于读取配置类
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,componentScan.getBoolean("useDefaultFilters"),this.resourceLoader);
// 1. 判断是否有nameGenerator注解
为扫描器设置beanName的生成器对象,并赋值给scanner,BeanNameGenerator的作用是为bean definitions生成Bean名字的接口
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass(
nameGenerator);
boolean useInheritedGenerator = (BeanNameGenerator.
generatorClass);
scanner.setBeanNameGenerator(useInheritedGenerator ?
.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
// 2. 判断是否有scopedProxy注解
ScopedProxyMode scopedProxyMode = componentScan.getEnum(
scopedProxyif (scopedProxyMode !=
ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
}
{
Class<? extends Scope
MetadataResolver> resolverClass = componentScan.getClass(
scopeResolver);
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
scanner.setResourcePattern(componentScan.getString(resourcePattern));
// 3. 判断属性中是否有includeFilters属性,有的话就添加到scanner中
设置componentScan中包含的过滤器 -- 在使用注解的时候配置了包含和排除的过滤器,这里进行处理
for (AnnotationAttributes filter : componentScan.getAnnotationArray(
includeFilters (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
// 4. 判断属性总是否有excludeFilters属性,有的话放到scnanner中
设置componentScan中排除的过滤器
excludeFilters (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
// 5. 判断是否有lazyInit属性
获取配置类中懒加载初始化的属性
boolean lazyInit = componentScan.getBoolean(
lazyInit (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit();
}
Set<String> basePackages =
();
// 6. 判断是否有basePackages属性
获取basePackages属性,也就是我们定义的包扫描路径
String[] basePackagesArray = componentScan.getStringArray(
basePackages (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(
.environment.resolvePlaceholders(pkg),ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Collections.addAll(basePackages,tokenized);
}
for (Class<?> clazz : componentScan.getClassArray(
basePackageClasses)) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
(basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(
false,1)">) {
@Override
boolean matchClassName(String className) {
declaringClass.equals(className);
}
});
// 调用scanner.doScan()方法,扫描basePackages包
scanner.doScan(StringUtils.toStringArray(basePackages));
}
调用doScan方法扫描配置类. 我们来看看主要做了哪些事情

第一步: 找到所有候选的BeanDefinition.
上面解析出了@ComponentScan注解传递过来的basePackages包. 扫描包中所有的类,得到候选类.
扫描的时候做了几件事呢? 看最上图最右侧部分. 这扫描出来就是我们的目标类.
第二步: 解析这些准目标类.
第三步: 设置默认的beanDefinition属性
@H_
502_49@
*
* 设置默认的bean定义的信息
* Apply the provided default values to this bean.
* @param defaults the default settings to apply
* @since 2.5
applyDefaults(BeanDefinitionDefaults defaults) {
设置这个类是不是懒加载的
Boolean lazyInit =
defaults.getLazyInit();
if (lazyInit !=
) {
setLazyInit(lazyInit);
}
设置默认的自动装配方式
setAutowireMode(defaults.getAutowireMode());
setDependencyCheck(defaults.getDependencyCheck());
设置初始化方法的名称
setInitMethodName(defaults.getInitMethodName());
是否可以调用InitMethod方法
setEnforceInitMethod(
);
setDestroyMethodName(defaults.getDestroyMethodName());
是否可以调用DestroyMethod方法
setEnforceDestroyMethod(
);
}
第四步: 将解析出来的bean定义注册到ioc容器中
这里就调用了BeanDefinitionReaderUtils.registerBeanDefinition注册bean定义. 之前注册过配置类,这里和其是一样的. 所以不再赘述了
这里有两个细节:
1. excludeFilter中排除了自己
@H_
502_49@
定义了一个类路径扫描器ClassPathBeanDefinitionScanner
这里的scanner用于读取配置类
ClassPathBeanDefinitionScanner scanner =
.registry,componentScan.getBoolean(useDefaultFilters"),1)">this.environment,1)">.resourceLoader);
1. 判断是否有nameGenerator注解
为扫描器设置beanName的生成器对象
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass(
.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
2. 判断是否有scopedProxy注解
ScopedProxyMode scopedProxyMode = componentScan.getEnum(
));
3. 判断属性中是否有includeFilters属性,有的话就添加到scanner中
(TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
4. 判断属性总是否有excludeFilters属性,有的话放到scnanner中
(TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
5. 判断是否有lazyInit属性
6. 判断是否有basePackages属性
(basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
想ExcludeFilter中添加默认的排除类,
scanner.addExcludeFilter() {
@Override
protected boolean matchClassName(String className) {
/**
* declaringClass就是配置类MainConfig,也就是说. 如果当前类是配置类,那么就会排除掉
* 这是一个钩子方法,现在不会调用. 后面才调用
* 在哪里调用呢?
*/
return declaringClass.equals(className);
}
});
调用scanner.doScan()方法,扫描basePackages包
scanner.doScan(StringUtils.toStringArray(basePackages));
}
在解析配置类的时候,除了@ComponentScan注解中定义的ExcludeFilter和IncludeFilter以外,还有默认的排除类. 如上加粗字体的部分. 这里是排除了配置类本身,我们这里的配置类是MainConfig,也就说,会排除掉自己.
@H_
502_49@
@Override
boolean matchClassName(String className) {
*
* declaringClass就是配置类MainConfig,现在不会调用. 后面才调用
* 在哪里调用呢? 先记住这个钩子方法matchClassName
*/
declaringClass.equals(className);
}
matchClassName是一个钩子方法. 在执行到这里的时候,不会真的去执行. 什么时候执行呢? 后面调用doScan的时候执行.
@H_
502_49@
protected Set<BeanDefinitionHolder>
doScan(String... basePackages) {
Assert.notEmpty(basePackages,1)">At least one base package must be specified);
Set<BeanDefinitionHolder> beanDefinitions =
循环包路径
(String basePackage : basePackages) {
// 第一步: 找到所有候选的BeanDefinition
*
* 在候选的配置类中,排除掉了自己,同时包含了默认的配置类
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
在寻找候选配置类的时候,进行了排除了配置类本身.
@H_
502_49@
public Set<BeanDefinition>
findCandidateComponents(String basePackage) {
this.componentsIndex !=
indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(
.componentsIndex,basePackage);
}
// 扫描basePackages,获取候选类
return scanCandidateComponents(basePackage);
}
}
进入这个方法
@H_
502_49@
private Set<BeanDefinition>
scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates =
第一步: 将com.lxl.www.iocbeanlifecicle转换成了物理路径com/lxl/www/iocbeanlifecicle
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) +
'/' +
.resourcePattern;
第二步: .getResources(...)读取到了包下所有的类
Resource[] resources =
getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled =
logger.isTraceEnabled();
boolean debugEnabled =
logger.isDebugEnabled();
(Resource resource : resources) {
(traceEnabled) {
logger.trace(Scanning resource);
}
第三步: 判断这个类是否是可读的?
(resource.isReadable()) {
{
MetadataReader MetadataReader =
getMetadataReaderFactory().getMetadataReader(resource);
第四步: 判断这个类是否是我们要排除的 或者 包含的
if (isCandidateComponent(MetadataReader)) {
通过scnner扫描出来的beanDefinition是ScannedGenericBeanDefinition类型
ScannedGenericBeanDefinition sbd =
ScannedGenericBeanDefinition(MetadataReader);
设置sbd的原类路径
sbd.setSource(resource);
在第四步的时候调用了isCandidateComponent(MetadataReader,这里就判断了是否是包含的类,或者是排除的类
@H_
502_49@
boolean isCandidateComponent(MetadataReader MetadataReader) throws IOException {
判断这个类类是否是我们设置的要排除的?
这里依然使用到了策略设计模式. TypeFilter是一个父类,不同子类的TypeFilter会调用不同的match方法
for (TypeFilter tf : this.excludeFilters) {
// 在这里面排除类配置类本身
if (tf.match(MetadataReader,getMetadataReaderFactory())) {
return false;
}
}
判断这个类是否是我们要包含的?
for (TypeFilter tf : this.includeFilters) {
if (tf.match(MetadataReader,getMetadataReaderFactory())) {
return isConditionMatch(MetadataReader);
}
}
;
}
紫色加错的部分是就是判读是否符合排除的类. 红色加错的部分是判断是否是包含的类.
先来看紫色的部分,排除的类
@H_
502_49@
boolean match(MetadataReader MetadataReader,MetadataReaderFactory MetadataReaderFactory)
throws IOException {
This method optimizes avoiding unnecessary creation of ClassReaders
as well as visiting over those readers.
(matchSelf(MetadataReader)) {
;
}
ClassMetadata Metadata =
MetadataReader.getClassMetadata();
// 排除配置类.
if (matchClassName(Metadata.getClassName())) {
return true;
}
看到了么,这里调用了matchClassName. 这就是上面定义的钩子方法,
@H_
502_49@
@Override
boolean matchClassName(String className) {
declaringClass.equals(className);
}
此时declaringClass表示的是当前的配置类,className表示的是目标类,如果当前目标类 == 配置类,那么就放回true. 返回true,则会排除掉
2. includeFilter中包含了默认的配置类
下面来看红色加错的部分
我们看到这里有this.includeFilters.包含的过滤器. 这里面是有值的

我们没有在配置类MainConfig上设置includeFilter啊,这里面怎么会有值呢?
这是因为我们有默认包含的过滤器,下面看看默认包含的过滤器是在哪里设置的.
首先从入口类点击AnnotationConfigApplicationContext

然后在点击this();

再点击ClassPathBeanDefinitionScanner

然后一路点击三个this(...)

最后看到上图 registerDefaultFilter();注册默认的过滤器
@H_
502_49@@SuppressWarnings(
unchecked registerDefaultFilters() {
注册默认的filter---第一个: 在includeFilter中增加了Component
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.
.getClassLoader();
{
注册默认的filter---第二个:在includeFilter中增加了 javax.annotation.ManagedBean
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean",cl)),false));
logger.trace(
JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning);
}
(ClassNotFoundException ex) {
JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
注册默认的filter---第三个:在includeFilter中增加了 javax.inject.Named
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named",false));
logger.trace(
JSR-330 'javax.inject.Named' annotation found and supported for component scanning JSR-330 API not available - simply skip.
}
}
如上图看到,注册了3个默认的过滤器. 分别是Component,ManagedBean,Named. 他们都是注解类型的过滤器AnnotationTypeFilter
其中javax.annotation.ManagedBean和javax.inject.Named是jdk提供给我们的.
到此为止,就将MainConfig配置类解析完并注册到ioc容器中了.