再回顾一下,ConfigurationClassPostProcessor类是用来解析配置类(@Configutration等)的后置处理器,类中使用ConfigurationClassParser类进行解析,
而对于@ComponentScan注解的解析使用ComponentScanAnnotationParser类来进行。
ComponentScanAnnotationParser类中实例化ClassPathBeanDefinitionScanner对象,并根据@ComponentScan注解上配置的各项属性,设置扫描对象属性并开始解析basePackages属性配置的路径下的BeanDefinition
//org.springframework.context.annotation.ComponentScanAnnotationParser#parse
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
// 实例化的时候设置默认Filters
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
// 获取bean的名用的
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
// scope代理
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
// 下边解释
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
// 下边解释
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
// 默认的延迟加载
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
// basePackagbes和basePackageClasses这都是设置扫描的基路径
// 一个是String串,一个是设置class,然后根据class获取包路径
Set<String> basePackages = new LinkedHashSet<>();
String[] basePackagesArray = componentScan.getStringArray("basePackagbes");
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Collections.addAll(basePackages, tokenized);
}
for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
@Override
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
});
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
这里根据源码看看,各项属性都是什么玩意
1、useDefaultFilters
默认值true
Scanner中有两个Filters集合
- List<TypeFilter> includeFilters,用来过滤需要扫描的类,这里边的如果匹配,则表示是个bean,要封装成beanDifinition加入beanFactory
- List<TypeFilter> excludeFilters,用来过滤需要扫描的类, 这里边的如果匹配,则这个类跳过、不被加入beanFactory
useDefaultFilters为true则为Scanner集合includeFilters设置默认filter(@Component, (javax.annotation.ManagedBean, javax.inject.Named))
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
在获取basepackage中的class文件集合之后过滤,判断扫描到的这个类是否是一个bean类
ClassPathBeanDefinitionScanner#doScan() --> findCandidateComponents() --> scanCandidateComponents() --> isCandidateComponent()
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
// 这个集合如果匹配,认为不是bean
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {
// 这个集合如果匹配,是bean
if (tf.match(metadataReader, this.metadataReaderFactory)) {
// 另有@Conditional注解相关操作,如果有@Conditional注解,并且匹配上了条件,则返回false,不再注入
// SpringBoot中各种@ConditonalOnXX都是基于此
return isConditionMatch(metadataReader);
}
}
return false;
}
private boolean isConditionMatch(MetadataReader metadataReader) {
if (this.conditionEvaluator == null) {
this.conditionEvaluator = new ConditionEvaluator(getRegistry(), getEnvironment(), getResourceLoader());
}
return !this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata());
}
2、nameGenerator
默认值 BeanNameGenerator.class
BeanNameGenerator这玩意是个接口,如果没有设置这个属性,会默认使用 AnnotationBeanNameGenerator ,用来获取beanBefinition的beanName
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = BeanNameGenerator.class == generatorClass;
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
3、scopedProxy
默认值 ScopedProxyMode.DEFAULT
4、scopeResolver
默认值 AnnotationScopeMetadataResolver.class
这两得另起一篇连@Scope注解一块了解了解,这里先跟Scanner源码看看什么路子
// 获取componentScan注解配置的scopedProxy属性
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
// 不是DEFAULT表示自定义了
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
// 有参构造一个AnnotationScopeMetadataResolver,默认ProxyMode
// 这波扫描进来的bean,除了用@Scope单独设置ScopedProxyMode的,其他的scope都被设置为这个默认ProxyMode
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
// 如果没配置,就是默认无参构造,里边的this.defaultProxyMode = ScopedProxyMode.NO
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
//org.springframework.context.annotation.ClassPathBeanDefinitionScanner#setScopedProxyMode
public void setScopedProxyMode(ScopedProxyMode scopedProxyMode) {
this.scopeMetadataResolver = new AnnotationScopeMetadataResolver(scopedProxyMode);
}
///org.springframework.context.annotation.AnnotationScopeMetadataResolver
public AnnotationScopeMetadataResolver(ScopedProxyMode defaultProxyMode) {
Assert.notNull(defaultProxyMode, "'defaultProxyMode' must not be null");
this.defaultProxyMode = defaultProxyMode;
}
在看这两宝贝哪里用到了
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 找到当前路径下的bean类集合
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
// 用AnnotationBeanNameGenerator 解析这个bean的@scope属性
// 取@Scope注解的各属性,如果@Scope没有配置ProxyMode属性,则取AnnotationBeanNameGenerator.defaultProxyMode
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
// scopeName,例如refresh,session等
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
// 这里对Scope进行代理,如果需要代理,则返回的这个definitionHolder已经狸猫换太子
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 注册beanDefition
// applyScopedProxyMode()方法中把原先需要代理的beanDefition换了个名字已经注册到beanFactory了,这里注册的是代理的新的BeanDefition
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
org.springframework.context.annotation.AnnotationScopeMetadataResolver#resolveScopeMetadata 这是默认的处理,也可以自定义一个MetaDataResolve
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
ScopeMetadata metadata = new ScopeMetadata();
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
annDef.getMetadata(), this.scopeAnnotationType);
if (attributes != null) {
metadata.setScopeName(attributes.getString("value"));
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = this.defaultProxyMode;
}
metadata.setScopedProxyMode(proxyMode);
}
}
return metadata;
}
自定义示例:scopeResolver=com.XXX.XXX.XXXScopeMetadataResolver.class
这么设置,扫描上来的每个bean都是原型模式,每次beanFactory.getBean(class/classname) 都获取的是一个新对象
public class XXXScopeMetadataResolver implements ScopeMetadataResolver
{
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition)
{
ScopeMetadata metadata = new ScopeMetadata();
metadata.setScopeName("prototype");
return metadata;
}
}
继续看ClassPathBeanDefinitionScanner#doScan,下边进行scope的代理操作
static BeanDefinitionHolder applyScopedProxyMode(
ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
// 这个No是无参构造函数AnnotationBeanNameGenerator中的defaultProxyMod
// 如果@ComponmentScan中ScopeProxy没有配置默认是DEFAULT,且类上没有@Scope注解或没有自定义属性proxyMode,那么当前scopedProxyMode就是No,直接返回
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definition;
}
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
// 否则创建代理
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
BeanDefinitionRegistry registry, boolean proxyTargetClass) {
// 获取原先这个BeanDefinition的名字和BeanDefition对象,比如原先叫 ABC
String originalBeanName = definition.getBeanName();
BeanDefinition targetDefinition = definition.getBeanDefinition();
// 要狸猫换太子,得给太子换个名字,原先的bean名字被改为了 scopedTarget.ABC
String targetBeanName = getTargetBeanName(originalBeanName);
// 创建一个新的BeanDefition来作为代理的beanDefition,把原先的对象作为成员设置进去
RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
proxyDefinition.setSource(definition.getSource());
proxyDefinition.setRole(targetDefinition.getRole());
proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
if (proxyTargetClass) {
targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
}
else {
proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
}
// 复制原先的属性Autowire、primary,然后原先的自然不能设置为true, 重新设置false
proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
proxyDefinition.setPrimary(targetDefinition.isPrimary());
if (targetDefinition instanceof AbstractBeanDefinition) {
proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
}
targetDefinition.setAutowireCandidate(false);
targetDefinition.setPrimary(false);
// 原先的BeanDefition还是注册到beanFactory中的,但是bean名已经改了
registry.registerBeanDefinition(targetBeanName, targetDefinition);
// 返回新的代理beanDeifition
return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}
5、resourcePattern
默认值是 "**/*.class",在扫描包路径下的类时用到 组了一下路径Pattern,检测符合这个Pattern的所有文件,返回一个Resource数组,然后就是判断哪个Resource是bean不是bean的
static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
6、includeFilters
值是@Filter[] ,为集合List<TypeFilter> includeFilters添加filter,自定义那些类要作为bean扫描进来
例如 includeFilters= {@Filter(type=FilterType.CUSTOM, classes=com.XXX.spring.XXXTpyeFilter.class)}
这么写就表示但凡是个类,都作为bean放入beanFactory
public class XXXTpyeFilter implements TypeFilter
{
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException
{
return true;
}
}
7、excludeFilters
基本同includeFilters
为集合List<TypeFilter> excludeFilters添加filter,和includeFilters相反
8、lazyInit
延迟加载默认false,容器refresh()最后实例化所有bean的时候用到,为true的beanDefition不实例化
总结之,除了比较基础的besePackages扫描路径设置之外,其他比较重要的
一、过滤类的:
useDefaultFilters(使用默认规则扫描@Component注解)、includeFilters和excludeFilters(自定义扫描规则)
二、scope代理的:
scopedProxy (bean的scope设置规则,先取类上注解@Scope的proxyMode,如果为DEFAULT再取这个scopedProxy属性,如果还是DEFAULT, 那么就不用scope代理,否则new一个BeanDefinition替换原先的名注册beanFactory,原先的beanDefinition也注册到了beanFactory只不过是beanName变为了 scopedTarget.beanName )
scopeResolver (自定义metadatascope的处理规则)