阅读须知
- Spring源码版本:4.3.8
- 文章中使用/* */注释的方法会做深入分析
正文
我们首先来看一个示例,用注解不用xml配置文件如何配置 Spring:
@Configuration
@ComponentScan(basePackages = {"com.test"})
@ImportResource("classpath:application-context.xml")
@Import(OtherConfiguration.class)
public class SpringConfiguration {
@Bean
@Scope("prototype")
public TestBean testBean() {
return new TestBean();
}
}
这样就完成了一个简单的 Spring 配置,我们来分别简单介绍一下示例中出现的各个注解的作用:
- @Configuration:我们可以把它理解为 Spring 的 xml 配置文件中的<beans/>标签,也就是 Spring 容器的上下文
- @Bean:我们可以把它理解为 Spring 的 xml 配置文件中的<bean/>标签,也就是用来注册一个 bean 的,我们可以配置 initMethod、destroyMethod 等注解属性来完成和<bean/>标签中对应属性配置一样的功能
- @Scope:用来配置bean的作用域,默认是 singleton,也就是单例
- @ComponentScan:我们可以把它理解为 Spring 的 xml 配置文件中的<context:component-scan/>标签,也就是用来扫描 @Component 注解注册 bean 的,如果未指定包,则将从声明此注解的类的包进行扫描
- @ImportResource:我们可以使用它来引入另一个 Spring 配置文件的配置
- @Import:我们可以使用它来引入另一个注解配置
启动时我们可以使用 AnnotationConfigApplicationContext 替换 ClassPathXmlApplicationContext 来启动Spring容器,eg:ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);
在 web 应用中,我们需要修改 web.xml 中的配置:
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.
support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
com.test.SpringConfiguration
</param-value>
</context-param>
这里的contextClass参数在默认不指定的情况下为XmlWebApplicationContext,所以我们在使用 xml 配置 Spring 的时候是不需要指定这个参数的。
在Spring源码解析之@Component注解的扫描文章结尾,我们看到 Spring 注册了 ConfigurationClassPostProcessor,它实现了 BeanFactoryPostProcessor,我们已经很多次的提及了这个接口的作用,这里就不再重复了,它会在 bean 创建之前调用,示例中出现的这些注解就是由 ConfigurationClassPostProcessor 来完成解析,我们来看实现:
ConfigurationClassPostProcessor:
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);
/* 解析 @Configuration 注解,注册 BeanDefinition */
processConfigBeanDefinitions(registry);
}
ConfigurationClassPostProcessor:
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
// 读取 BeanDefinition 注册中心中已经存在的 BeanDefinition 的 beanName
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 判断如果已经处理过,无需再次处理
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
/* 判断是否含有相关的几个注解 */
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 没有@Configuration直接返回
if (configCandidates.isEmpty()) {
return;
}
// 按照注解的@Order进行排序
Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
@Override
public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}
});
SingletonBeanRegistry sbr = null;
// 如果有自定义的beanName生成器,则应用
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
// @Configuration注解的解析器
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
do {
/* 解析 */
parser.parse(candidates);
// 因为CGLIB代理的关系,这里需要校验@Configuration注解的类和@Bean注解的方法都是可以被覆盖的,也就是类不能被final修饰,方法可以重写
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
// 移除已经解析过的
configClasses.removeAll(alreadyParsed);
if (this.reader == null) {
// 创建BeanDefinitionReader
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
/* 加载BeanDefinition */
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
// 个人理解这个判断的含义是在这期间可能有新的BeanDefinition被注册了,所以要判断新注册的BeanDefinition中是否有需要解析的
if (registry.getBeanDefinitionCount() > candidateNames.length) {
// 获取新的beanDefinitionNames
String[] newCandidateNames = registry.getBeanDefinitionNames();
// 旧的beanDefinitionNames
Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
// 保存已经解析过的className
Set<String> alreadyParsedClasses = new HashSet<String>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
// 遍历新的beanDefinitionNames
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
// 如果在旧的中不包含并且class没有被解析过,则判断是否需要解析
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
if (sbr != null) {
// 对ImportAware的支持
if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
}
// 清理元数据缓存
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
ConfigurationClassUtils:
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
String className = beanDef.getBeanClassName();
if (className == null) {
return false;
}
AnnotationMetadata metadata;
// 根据不同类型的的BeanDefinition获取对应的metadata元数据
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
metadata = new StandardAnnotationMetadata(beanClass, true);
}
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)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
/* 判断是否有另外相关的几个注解 */
else if (isLiteConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
// 如果有@Order注解,设置order属性用于排序
Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
if (orderAttributes != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, orderAttributes.get(AnnotationUtils.VALUE));
}
return true;
}
ConfigurationClassUtils:
public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
// 是否有@Configuration类注解
return metadata.isAnnotated(Configuration.class.getName());
}
ConfigurationClassUtils:
public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) {
// 接口不通过
if (metadata.isInterface()) {
return false;
}
/* 是否有candidateIndicators中包含的类注解 */
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
try {
// 是否有@Bean方法注解
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;
}
}
ConfigurationClassUtils:
static {
candidateIndicators.add(Component.class.getName());
candidateIndicators.add(ComponentScan.class.getName());
candidateIndicators.add(Import.class.getName());
candidateIndicators.add(ImportResource.class.getName());
}
下面就是配置解析的流程:
ConfigurationClassParser:
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
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:
protected final void parse(String className, String beanName) throws IOException {
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
/* 解析配置 */
processConfigurationClass(new ConfigurationClass(reader, beanName));
}
protected final void parse(Class<?> clazz, String beanName) throws IOException {
/* 解析配置 */
processConfigurationClass(new ConfigurationClass(clazz, beanName));
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
/* 解析配置 */
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
三个重载的parse方法最终都会被包装成ConfigurationClass调用processConfigurationClass方法:
ConfigurationClassParser:
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
/* 判断是否需要跳过 */
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
// 是否已经配置过
if (existingClass != null) {
// 是否已经注册
if (configClass.isImported()) {
if (existingClass.isImported()) {
// 已经存在的ConfigurationClass合并新ConfigurationClass的导入者
existingClass.mergeImportedBy(configClass);
}
// 注册过无需再次注册
return;
}
else {
// 这里代表有重复的BeanDefinition,将已经存在的去掉重新注册
this.configurationClasses.remove(configClass);
for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext();) {
if (configClass.equals(it.next())) {
it.remove();
}
}
}
}
// 递归处理当前ConfigurationClass和它的父类
SourceClass sourceClass = asSourceClass(configClass);
do {
/* 处理ConfigurationClass */
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
// 保存已经处理过的ConfigurationClass
this.configurationClasses.put(configClass, configClass);
}
ConditionEvaluator:
public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase) {
// 是否有@Conditional注解,没有则不用判断其中配置的条件,无需跳过
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
// 如果处理阶段(包括解析配置阶段和注册bean阶段)等于null,递归判断是否需要跳过
if (phase == null) {
// 这里判断的几个注解与上面是相同的
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
List<Condition> conditions = new ArrayList<Condition>();
// 遍历@Conditional的value属性值
for (String[] conditionClasses : getConditionClasses(metadata)) {
for (String conditionClass : conditionClasses) {
// 转换成Condition对象
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
conditions.add(condition);
}
}
// 按照order排序
AnnotationAwareOrderComparator.sort(conditions);
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
if (requiredPhase == null || requiredPhase == phase) {
// 如果Condition条件不匹配,则需要跳过
if (!condition.matches(this.context, metadata)) {
return true;
}
}
}
return false;
}
这里简单介绍一下@Conditional注解,注意不是上文的@Configuration注解,我们可以实现Condition接口来定义个性化的匹配条件,并在@Conditional注解中声明这些Condition,Spring会按照我们定义的条件来确定是否创建注解范围内的bean。
ConfigurationClassParser:
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// 递归处理成员内部类
processMemberClasses(configClass, sourceClass);
// 提取@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");
}
}
// 提取@ComponentScan注解的属性遍历进行处理
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
// 同样的@Conditional注解条件判断
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
/* 解析 */
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 如果扫描生成的BeanDefinition有需要进一步处理的,递归再次进行同样的解析处理
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
if (ConfigurationClassUtils.checkConfigurationClassCandidate(
holder.getBeanDefinition(), this.metadataReaderFactory)) {
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
}
}
}
/* 提取@Import注解的属性遍历进行处理 */
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 提取@ImportResource注解的属性遍历进行处理
if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
// locations属性
String[] resources = importResource.getStringArray("locations");
// reader属性
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
// 处理路径中的特殊符号
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
/* 提取@Bean注解的方法的元数据 */
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 处理实现的所有接口中@Bean注解的方法,去上面的处理方法一样,但不是抽象方法,因为java8中接口有默认方法和其他具体方法,这里只会处理这些方法的@Bean注解
processInterfaces(configClass, sourceClass);
// 处理父类
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
// java包的父类和已经处理过的父类不处理
if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
// 标记父类已经处理过
this.knownSuperclasses.put(superclass, configClass);
// 返回父类的SourceClass再次进行递归处理
return sourceClass.getSuperClass();
}
}
return null;
}
ConfigurationClassParser:
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
// name属性
String name = propertySource.getString("name");
if (!StringUtils.hasLength(name)) {
name = null;
}
// encoding属性
String encoding = propertySource.getString("encoding");
if (!StringUtils.hasLength(encoding)) {
encoding = null;
}
// value属性
String[] locations = propertySource.getStringArray("value");
Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
// ignoreResourceNotFound属性
boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
// factory属性
Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
for (String location : locations) {
try {
// 处理路径中的特殊字符
String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
// 根据路径获取资源
Resource resource = this.resourceLoader.getResource(resolvedLocation);
// 添加属性到Environment环境对象中的propertySources中,
addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
}
catch (IllegalArgumentException ex) {
if (ignoreResourceNotFound) {
if (logger.isInfoEnabled()) {
logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
}
}
else {
throw ex;
}
}
catch (IOException ex) {
if (ignoreResourceNotFound &&
(ex instanceof FileNotFoundException || ex instanceof UnknownHostException)) {
if (logger.isInfoEnabled()) {
logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
}
}
else {
throw ex;
}
}
}
}
ComponentScanAnnotationParser:
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
Assert.state(this.environment != null, "Environment must not be null");
Assert.state(this.resourceLoader != null, "ResourceLoader must not be null");
// 创建Scanner
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
// nameGenerator属性
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
// scopedProxy属性
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
// scopeResolver属性
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
// resourcePattern属性
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
// includeFilters属性
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
// excludeFilters属性
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
// lazyInit属性
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
Set<String> basePackages = new LinkedHashSet<String>();
// basePackages属性
String[] basePackagesArray = componentScan.getStringArray("basePackages");
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
basePackages.addAll(Arrays.asList(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));
}
这里看起来是不是很熟悉,没错啦,我们在分析<context:component-scan/>
标签的解析时也是同样的流程,只不过这里是解析注解方式的@ComponentScan。
ConfigurationClassParser:
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) throws IOException {
if (importCandidates.isEmpty()) {
return;
}
// 栈中链式导入的检查,检查正在导入的class是否有冲突
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
// 入栈标识正在解析中
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
// 我们可以实现ImportSelector来决定导入哪些配置
if (candidate.isAssignable(ImportSelector.class)) {
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
// 执行selector实现的Aware的相关set方法
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
// 如果是延迟导入的selector添加到延迟导入的集合中稍后处理
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
else {
// 提取
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
// 递归解析
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
// 我们可以实现ImportBeanDefinitionRegistrar来注册额外的BeanDefinition
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// 如果两者都不是就按照@Configuration注解类的解析方式再次解析一遍
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 import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
// 出栈表示已经解析完
this.importStack.pop();
}
}
}
这里我们看到了两个接口ImportSelector和ImportBeanDefinitionRegistrar,这两个接口在Spring boot中有非常重要的作用,详见笔者关于Spring boot源码分析的文章。
下面是延迟导入的处理:
ConfigurationClassParser:
private void processDeferredImportSelectors() {
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
// 排序
Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR);
for (DeferredImportSelectorHolder deferredImport : deferredImports) {
ConfigurationClass configClass = deferredImport.getConfigurationClass();
try {
// 同样的提取
String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
// 同样的处理
processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
}
}
最后就是注册BeanDefinition了:
ConfigurationClassBeanDefinitionReader:
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
/* 加载BeanDefinition */
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
ConfigurationClassBeanDefinitionReader:
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
TrackedConditionEvaluator trackedConditionEvaluator) {
// 判断是否需要跳过,与之前解析@Configuration判断是否跳过的逻辑是相同的
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;
}
if (configClass.isImported()) {
/* 注册@Configuration注解的当前类为一个BeanDefinition */
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
/* 加载@Bean注解的方法需要生成的BeanDefinition */
loadBeanDefinitionsForBeanMethod(beanMethod);
}
/* 加载@ImportResource注解配置的资源需要生成的BeanDefinition */
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 调用自定义的ImportBeanDefinitionRegistrar的registerBeanDefinitions方法注册BeanDefinition
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
ConfigurationClassBeanDefinitionReader:
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
AnnotationMetadata metadata = configClass.getMetadata();
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
// scope属性解析
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
// 生成beanName
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);
// 注册BeanDefinition
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
if (logger.isDebugEnabled()) {
logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
}
}
大部分过程我们之前都分析过。
AnnotationConfigUtils:
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
// @Lazy注解属性提取和设置
if (metadata.isAnnotated(Lazy.class.getName())) {
abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
}
else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) {
abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value"));
}
// @Primary注解属性提取和设置
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
// @DependsOn注解属性提取和设置
if (metadata.isAnnotated(DependsOn.class.getName())) {
abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
}
if (abd instanceof AbstractBeanDefinition) {
AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
// @Role注解属性提取和设置
if (metadata.isAnnotated(Role.class.getName())) {
absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue());
}
// @Description注解属性提取和设置
if (metadata.isAnnotated(Description.class.getName())) {
absBd.setDescription(attributesFor(metadata, Description.class).getString("value"));
}
}
}
ConfigurationClassBeanDefinitionReader:
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = beanMethod.getMetadata();
String methodName = metadata.getMethodName();
// 相同的是否需要跳过的判断
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
configClass.skippedBeanMethods.add(methodName);
return;
}
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
// @Bean注解属性的提取
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
// name属性
List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
for (String alias : names) {
// 注册别名
this.registry.registerAlias(beanName, alias);
}
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
return;
}
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
beanDef.setResource(configClass.getResource());
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
// 对@Bean注解的静态方法和普通方法的不同处理
if (metadata.isStatic()) {
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
beanDef.setFactoryMethodName(methodName);
}
else {
beanDef.setFactoryBeanName(configClass.getBeanName());
beanDef.setUniqueFactoryMethodName(methodName);
}
beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
// 通用注解的解析和设置
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
// autowire属性
Autowire autowire = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
// initMethod属性
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
// destroyMethod属性
String destroyMethodName = bean.getString("destroyMethod");
if (destroyMethodName != null) {
beanDef.setDestroyMethodName(destroyMethodName);
}
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
// @Scope注解属性提取
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
// value属性
beanDef.setScope(attributes.getString("value"));
// proxyMode属性
proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) {
// 代理模式的应用
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry,
proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
}
if (logger.isDebugEnabled()) {
logger.debug(String.format("Registering bean definition for @Bean method %s.%s()",
configClass.getMetadata().getClassName(), beanName));
}
this.registry.registerBeanDefinition(beanName, beanDefToRegister); // 注册BeanDefinition
}
其中大部分过程我们在默认标签解析的文章中分析bean标签的解析时都阐述过,这里不再重复说明。
ConfigurationClassBeanDefinitionReader:
private void loadBeanDefinitionsFromImportedResources(
Map<String, Class<? extends BeanDefinitionReader>> importedResources) {
Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<Class<?>, BeanDefinitionReader>();
for (Map.Entry<String, Class<? extends BeanDefinitionReader>> entry : importedResources.entrySet()) {
String resource = entry.getKey();
Class<? extends BeanDefinitionReader> readerClass = entry.getValue();
if (BeanDefinitionReader.class == readerClass) {
// 根据配置资源的后缀判断使用哪种BeanDefinitionReader
if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
readerClass = GroovyBeanDefinitionReader.class;
}
else {
readerClass = XmlBeanDefinitionReader.class;
}
}
BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
if (reader == null) {
try {
// 缓存中没有则进行初始化
reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry);
if (reader instanceof AbstractBeanDefinitionReader) {
AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader);
abdr.setResourceLoader(this.resourceLoader);
abdr.setEnvironment(this.environment);
}
readerInstanceCache.put(readerClass, reader);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]");
}
}
// 加载BeanDefinition
reader.loadBeanDefinitions(resource);
}
}
到这里,以注解方式配置Spring的源码分析就完成了。