目录
1. postProcessBeanDefinitionRegistry()
(2)@Component、@ComponentScan、@Import、@ImportSource等注解的解析
a. @Component、@ComponentScan、@Import、@ImportSource解析
现如今,我们在使用Spring框架时,基本都是基于注解的方式进行Bean的注入,如:@PropertySource、@ComponentScan、@Bean、@Import、@ImportSource、@Configuration、ImportSelector,它们的解析,都离不开ConfigurationClassPostProcessor类,这些注解就是去扫描(或引入),把扫描(或引入)的类放到Spring容器,变成BeanDefinition。
之前我们都是通过基于XML的方式注册Spring上下文,现在,通过注解上下文的方式已经大行其道,如下:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanBean.class);
通过@ComponentScan注解将包路径导入:
@Component
@ComponentScan(value = "com.baec.kieasar")
public class ScanBean {
}
或者:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.baec.kieasar");
我们看AnnotationConfigApplicationContext的构造函数:
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
进入AnnotatedBeanDefinitionReader的构造函数:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
进入this():
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
进入AnnotationConfigUtils.registerAnnotationConfigProcessors()方法
所属类:org.springframework.context.annotation.AnnotationConfigUtils
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
ConfigurationClassPostProcessor就是在这里注册进来的:
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
// 设置beanFactory的OrderComparator为AnnotationAwareOrderComparator
// 它是一个Comparator(比较器),用来排序,比如new ArrayList<>().sort(Comparator)
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
// ContextAnnotationAutowireCandidateResolver类是注解候选解析器(主要处理@Lazy),用来推断某个Bean是否需要依赖注入
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
// 注册ConfigurationClassPostProcessor类型的BeanDefinition
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册AutowiredAnnotationBeanPostProcessor类型的BeanDefinition
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
// 注册CommonAnnotationBeanPostProcessor类型的BeanDefinition
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
// 注册PersistenceAnnotationBeanPostProcessor类型的BeanDefinition
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册EventListenerMethodProcessor类型的BeanDefinition,用来处理@EventListener注解
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
// 注册DefaultEventListenerFactory类型的BeanDefinition,用来处理@EventListener注解
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
首先,我们先看一下ConfigurationClassPostProcessor类的继承关系:
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, ApplicationStartupAware, BeanClassLoaderAware, EnvironmentAware {
该类实现了BeanDefinitionRegistryPostProcessor接口,用来操作(注册)BeanDefinition,并加入到BeanDefinitionRegistry中。PriorityOrdered接口是用来做排序的,它继承Ordered接口,重写了getOrder()方法:
@Override
// 设定执行顺序,值越小,先执行
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE; // within PriorityOrdered
}
1. postProcessBeanDefinitionRegistry()
同时实现了BeanDefinitionRegistyPostProcessor接口,必然会实现postProcessBeanDefinitionRegistry()方法,注册BeanDefinition,扫描配置类,我们先看这个方法:
/**
* Derive further bean definitions from the configuration classes in the registry.
* 这是BeanDefinitionRegistryPostProcessor接口BeanFactoryPostProcessor的方法,进行了重写
*/
@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);
// TODO 核心逻辑解析配置类,重点看---->
processConfigBeanDefinitions(registry);
}
进入本类的processConfigBeanDefinitions()方法:
/**
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
* 在这个方法中就是对所有的beanDefinition操作(解析)
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 获取所有的beanNames
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 如果有该标识就不再处理,"configurationClass" 表示有那些注解,如:@Configuration
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
// 判断是否为配置类,是否有需要处理的BeanDefinition,如果是,则放入configCandidates
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
// 如果容器为空,即找不到@Configuration类,则立即返回
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
// 对需要处理的BeanDeanDefinition排序,值越小越靠前
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// 解析配置类,BeanDefinition解析器————ConfigurationClassParser
// Parse each @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 = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// TODO 解析的核心流程,重要程度:5
// 先收集,如@Import、@ComponentScan、@Bean、ImportSelector,最终封装成BeanDefinition
// 解析,会先把BeanDefinitionHolder封装成ConfigurationClass
// 在这个过程中会进行扫描、导入等步骤,从而找到其他的ConfigurationClass
parser.parse(candidates);
parser.validate();
// ConfigurationClass相当于截止到当前,解析得到的所有配置类(包括本身)
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// TODO 再调用,上面的parse()方法对一些注解没有扫描到,所以在这里进行调用。
// 解析,会先把BeanDefinitionHolder封装成ConfigurationClass
// 在这个过程中会进行扫描、导入等步骤,从而找到其他的ConfigurationClass
this.reader.loadBeanDefinitions(configClasses);
// 已经解析完的类,再一个递归进来不必重复处理
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
candidates.clear();
// 比较差异,如果发现有新的BeanDefiniton,再走一遍解析流程
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
// 检查多出来的BeanDefinition是否为配置类,是否需要解析
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
进入parse()方法:
所属类:org.springframework.context.annotation.ConfigurationClassParser
// 解析过程
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
// 通过扫描注解方式得到的BeanDefinition
if (bd instanceof AnnotatedBeanDefinition) {
// 看这个方法*****
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
// 不是通过扫描注解得到的BeanDefinition
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);
}
}
// TODO 处理DeferredImportSelector接口的解析,当前所有的配置类解析之后才执行
// DeferredImportSelector表示推迟的ImportSelector,正常的ImportSelector是在解析配置类过程中执行的
this.deferredImportSelectorHandler.process();
}
进入本类的parse()方法:
所属类:org.springframework.context.annotation.ConfigurationClassParser
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
// 把metadata对象和beanName封装成ConfigurationClass对象
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
进入本类的processConfigurationClass()方法,这里是真正的解析逻辑:
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
// 对@Conditional注解的支持,过滤掉不需要实例化的类
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
// 如果一个类被两个类import了,就符合这个条件,加到importBy这个属性中
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// Recursively process the configuration class and its superclass hierarchy.
// 这个对象可以理解为跟类或者跟接口对应,然后把metadata对象包装进去
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
// TODO 核心代码-->
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
// 收集完之后放到Map中
this.configurationClasses.put(configClass, configClass);
}
(1)@Conditional注解解析
首先解析的是@Conditional注解,@Conditional注解在Springboot中使用较多,作用就是设置该类实例化的条件,如:
@Conditional(value = {CustomCondition.class})
@Primary
@Bean
public Lison lison() {
return new Lison();
}
Lison类实例化需要依赖CustomCondition,也可以是数组,被依赖的类CustomCondition需要实现Condition接口,实现matches()方法:
public class CustomCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return true;
}
}
进入@Conditional注解的解析方法shouldSkip():
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
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<>();
// 获取@Conditional注解的value值
for (String[] conditionClasses : getConditionClasses(metadata)) {
for (String conditionClass : conditionClasses) {
// 反射实例花Condition对象
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
conditions.add(condition);
}
}
// 排序(支持Order接口、@Order注解)
AnnotationAwareOrderComparator.sort(conditions);
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
// 循环调用每一个condition的matches()方法
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
return true;
}
}
return false;
}
(2)@Component、@ComponentScan、@Import、@ImportSource等注解的解析
回到processConfigurationClass()方法,进入核心代码doProcessConfigurationClass() 方法:
所属类:org.springframework.context.annotation.ConfigurationClassParser
/*
* TODO 注解解析核心方法 SourceClass代表对类的封装,负责的方向不一样,里面有个metaData对象
*/
@Nullable
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
// 判断类上面是否有@Component注解
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
// TODO 递归处理有@Component注解的【对内部类的处理】
processMemberClasses(configClass, sourceClass, filter);
}
// Process any @PropertySource annotations
// 处理@PropertySources和@PropertySource注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
// TODO 核心逻辑———>
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// Process any @ComponentScan annotations
// 处理@ComponentScans和@ComponentScan注解,从sourceClass.getMetadata()拿到注解,放到Set容器
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
// 是否需要跳过
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
// TODO 下面这个parse()方法中的逻辑,跟<component-scan>自定义标签解析的逻辑类似,
// 通过ClassPathBeanDefinitionScanner去扫描,得到BeanDefiniiton,注册到Spring容器
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
// 这里递归扫描到@Component生成beanDefinition后,又递归去检验类上面是否有特殊注解
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
// 判断是否是候选的BeanDefinition,如果是,则parse(),又是递归处理
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
// TODO 处理@Import注解,getImports(sourceClass)方法用来收集类上面的@Import注解,并封装成SourceClass
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// Process any @ImportResource annotations
// 处理@ImportResource注解,作用不大,加载xml文件
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);
// 建立xml文件和reader的映射关系
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods
// (重点)处理@Bean注解,收集有@Bean注解的方法,sourceClass为当前类
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
// 加入到ConfigurationClass中
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
// 处理有@Bean注解方法对应的接口,逻辑差不多
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;
}
上面方法我们用一个图来归纳:
a. @Component、@ComponentScan、@Import、@ImportSource解析
对@Component、@ComponentScan、@Import、@ImportSource注解的判断,在isConfigurationCandidate()方法中:
所属类:org.springframework.context.annotation.ConfigurationClassUtils
public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
// Do not consider an interface or an annotation...
if (metadata.isInterface()) {
return false;
}
// Any of the typical annotations found?
// 如果存在@Component、@ComponentScan、@Import、@ImportSource注解中的一个,就是lite配置类
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
// Finally, let's look for @Bean methods...
// 如果存在@Bean注解的方法,就是lite配置类
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;
}
}
abstract class ConfigurationClassUtils {
public static final String CONFIGURATION_CLASS_FULL = "full";
public static final String CONFIGURATION_CLASS_LITE = "lite";
public static final String CONFIGURATION_CLASS_ATTRIBUTE =
Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "configurationClass");
private static final String ORDER_ATTRIBUTE =
Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "order");
private static final Log logger = LogFactory.getLog(ConfigurationClassUtils.class);
private static final Set<String> candidateIndicators = new HashSet<>(8);
static {
candidateIndicators.add(Component.class.getName());
candidateIndicators.add(ComponentScan.class.getName());
candidateIndicators.add(Import.class.getName());
candidateIndicators.add(ImportResource.class.getName());
}
b. @Configuration解析
对@Configuration注解的类,Spring判依据是以下几种:
- 如果有@Configuration注解的类,并且proxyBeanMethods为true或null(默认)时,就是Full配置类;
- 如果有@Configuration注解,但proxyBeanMethods为false时,为lite配置类;
- 如果不存在@Configuration注解,但只要存在@Component、@ComponentScan、@Import、@ImportSource,就是lite配置类;
- 如果不存在@Configuration注解,但只要有@Bean注解的方法,就是lite配置类。
c. @ComponentScans解析
会创建一个ClassPathBeanDefinitionScanner扫描器,调用doScan()方法:
所属类:org.springframework.context.annotation.ClassPathBeanDefinitionScanner
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) {
// 根据扫描路径,得到BeanDefinition
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
// 解析class
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
// 解析@lazy、@Primary、@DependsOn、@Role、@Description
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 检查Spring容器是否已经存在beanName
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 注册
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
在doProcessConfigurationClass()方法,只有@ComponentScan注解的解析,会通过扫描生成BeanDefinition,其他注解都是添加到了ConfigurationClass类的置属性,(此时还没有解析)。
d. 内部类处理
看本类的processMemberClasses(configClass, sourceClass, filter),处理有@Component注解的,这是对内部类的处理:
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,
Predicate<String> filter) throws IOException {
// 获取该类的内部类并包装成sourceClass对象,可以进去看看getMemberClasses()方法
Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
if (!memberClasses.isEmpty()) {
List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
for (SourceClass memberClass : memberClasses) {
// 如果是需要处理的,有@Bean、@Component等注解
if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
candidates.add(memberClass);
}
}
// 排序
OrderComparator.sort(candidates);
// 循环处理每一个内部类
for (SourceClass candidate : candidates) {
if (this.importStack.contains(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
// candidate是子类,configClass是父类,candidate是configClass的内部类,递归处理
processConfigurationClass(candidate.asConfigClass(configClass), filter);
}
finally {
this.importStack.pop();
}
}
}
}
}
ConfigurationClass类是用来封装配置类的,我们看一下它的成员属性:
// 该类是对一个类的包装,收集注解的作用(也包括对内部类)
final class ConfigurationClass {
// 类中的基本源信息,类、方法、注解信息
private final AnnotationMetadata metadata;
// 类中流的封装
private final Resource resource;
@Nullable
private String beanName;
// 代表由哪个类导入进来的,装的是被引用来或者外部类
private final Set<ConfigurationClass> importedBy = new LinkedHashSet<>(1);
// 如果所在类有@Bean注解的方法,放在这个容器中
private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();
// 如果所在类有@ImportedResources注解,放到这个容器中
private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
new LinkedHashMap<>();
// 如果所在类实现了ImportBeanDefinitionRegistrar接口,放在这个容器中
private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
new LinkedHashMap<>();
d. @PropertySource解析
进入本类的 processPropertySource(propertySource)方法,把配置文件解析出来放到environment中:
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
String name = propertySource.getString("name");
if (!StringUtils.hasLength(name)) {
name = null;
}
String encoding = propertySource.getString("encoding");
if (!StringUtils.hasLength(encoding)) {
encoding = null;
}
// 获取配置文件路径
String[] locations = propertySource.getStringArray("value");
Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
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 resource = this.resourceLoader.getResource(resolvedLocation);
// 加载Resource中的配置值属性,封装成Properties对象,并创建PropertySource对象加入到Environment
addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
}
catch (IllegalArgumentException | FileNotFoundException | UnknownHostException ex) {
// Placeholders not resolvable or resource not found when trying to open it
if (ignoreResourceNotFound) {
if (logger.isInfoEnabled()) {
logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
}
}
else {
throw ex;
}
}
}
}
SourceClass的组成:
private class SourceClass implements Ordered {
private final Object source; // Class or MetadataReader
private final AnnotationMetadata metadata;
e. @Import解析
@Imprt注解的作用就是将某个类导入到Spring的容器,并将其实例化。例如:
@Component
// Import虽然是实例化一个类,Import进来的类可以实现一些接口,如:ImportSelector和ImportBeanDefinitionRegistar接口,
// 然后我们可以调用接口中的方法,但是通过@Component注解注入的类如果实现了这些接口,却不能调用其方法。
@Import(DeferredImportSelectorDemo.class)
// @Import({DeferredImportSelectorDemo.class, LisonSelectImport.class, AwareBean.class})
@EnableAspectJAutoProxy
public class ImportBean {
}
例子中的ImportBean加了@Imprt注解,解析流程就是把ImportBean类包装成SourceClass对象,然后从metadata方法拿到@Import注解,并拿到它的value值,放到Set容器中。value值也可以是数组,导入多个类。
public class LisonSelectImport implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
MergedAnnotations annotations = importingClassMetadata.getAnnotations();
MergedAnnotation<EnableAspectJAutoProxy> eas = annotations.get(EnableAspectJAutoProxy.class);
Object proxyTargetClass = eas.getValue("proxyTargetClass").get();
// 类的完整限定名,
return new String[]{Jack.class.getName()};
}
}
同时也可以拿到引入的这个类ImportBean上面的注解信息,如:@EnableAspectJAutoProxy开启切面功能的注解,Springboot自动配置就是这样实现的。
进入@Import注解解析的核心方法processImports():
所属类:本类org.springframework.context.annotation.ConfigurationClassParser
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
// 如果没有@Import注解直接返回,不处理
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
// 循环类上面的每一个@Import
for (SourceClass candidate : importCandidates) {
// 如果Import进来的是一个ImportSelector类型
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
// 反射实例化
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
// 如果是DeferredImportSelector类型
if (selector instanceof DeferredImportSelector) {
// 比较复杂,Springboot中自动配置用到
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
// 调用ImportSelectors()方法,返回所有需要import到Spring容器的beanName,这里会调到自己写的实现类方法,返回的是类的完整限定名。
// selectImports()方法是在收集之前调用的
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
// 递归处理,有时import进来的类又有@Import注解
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
// 如果@Import的类是ImportBeanDefinitionRegistrar类型
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 =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
// 加入到ImportBeanDefinitionRegistrar容器中,这里还没有调用registerBeanDefinitions(),在收集之后调用该接口的实现方法
// addImportBeanDefinitionRegistrar()维护了一个实现ImportBeanDefinitionRegistrar接口的实例和该类的AnnotationMetadata的映射关系
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
// 如果不是ImportSelector或ImportBeanDefinitionRegistrar类型,将其作为@Configuration类进行处理
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
// 如果Import进来的类有其他注解,则进入这里,递归调用进行解析
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
}
接下来回到processConfigBeanDefinitions()方法,看this.reader.loadBeanDefinitions()方法,这是对@Bean、@ImportedResource、ImportBeanDefinitionRegistrar处理逻辑,解析注解的方法。 配置类解析完成之后会加到当前ConfigurationClass对应的属性中,接下来才会进一步解析(或构建)成BeanDefiniton。
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
// 注解收集,为类本身及其有@Bean注解的方法封装成BeanDefinition
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
这个方法主要就是解析配置类生成BeanDefinition。
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进来的类,和内部类走这里变成BeanDefinition
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// @Bean注解的方法变成BeanDefinition
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// 处理@ImportResource注解,xml解析流程
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 处理ImportBeanDefinitionRegistrar接口,调用registrerBeanDefinitions()方法
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
进入loadBeanDefinitionsForBeanMethod():
所属类:org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = beanMethod.getMetadata();
String methodName = metadata.getMethodName();
// Do we need to mark the bean as skipped by its condition?
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
configClass.skippedBeanMethods.add(methodName);
return;
}
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
Assert.state(bean != null, "No @Bean annotation attributes");
// Consider name and any aliases
List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
// Register aliases even when overridden
for (String alias : names) {
this.registry.registerAlias(beanName, alias);
}
// Has this effectively been overridden before (e.g. via XML)?
// 如果出现重复的@Bean注解的方法名(比如方法重载),则return,不会生成新的
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
"' clashes with bean name for containing configuration class; please make those names unique!");
}
return;
}
// 不存在则生成一个新的BeanDefinition
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
if (metadata.isStatic()) {
// static @Bean method
if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
}
else {
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
}
beanDef.setUniqueFactoryMethodName(methodName);
}
else {
// instance @Bean method
beanDef.setFactoryBeanName(configClass.getBeanName());
beanDef.setUniqueFactoryMethodName(methodName);
}
if (metadata instanceof StandardMethodMetadata) {
beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
}
beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
Autowire autowire = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
boolean autowireCandidate = bean.getBoolean("autowireCandidate");
if (!autowireCandidate) {
beanDef.setAutowireCandidate(false);
}
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
// Consider scoping
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
beanDef.setScope(attributes.getString("value"));
proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
// Replace the original bean definition with the target one, if necessary
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.isTraceEnabled()) {
logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
configClass.getMetadata().getClassName(), beanName));
}
// 把解析出来的BeanDefiniton注册进去,这里会检查是否允许覆盖
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) {
if (!this.registry.containsBeanDefinition(beanName)) {
return false;
}
BeanDefinition existingBeanDef = this.registry.getBeanDefinition(beanName);
// Is the existing bean definition one that was created from a configuration class?
// -> allow the current bean method to override, since both are at second-pass level.
// However, if the bean method is an overloaded case on the same configuration class,
// preserve the existing bean definition.
// 如果@Bean对应的beanName已经存在BeanDefinition,那么则把此BeanDefinition的isFactoryMethodUnique设置为false
// 后续根据此BeanDefinition取创建Bean时,就知道不止一个
if (existingBeanDef instanceof ConfigurationClassBeanDefinition) {
ConfigurationClassBeanDefinition ccbd = (ConfigurationClassBeanDefinition) existingBeanDef;
if (ccbd.getMetadata().getClassName().equals(
beanMethod.getConfigurationClass().getMetadata().getClassName())) {
if (ccbd.getFactoryMethodMetadata().getMethodName().equals(ccbd.getFactoryMethodName())) {
ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName());
}
return true;
}
else {
return false;
}
}
// A bean definition resulting from a component scan can be silently overridden
// by an @Bean method, as of 4.2...
if (existingBeanDef instanceof ScannedGenericBeanDefinition) {
return false;
}
// Has the existing bean definition bean marked as a framework-generated bean?
// -> allow the current bean method to override it, since it is application-level
if (existingBeanDef.getRole() > BeanDefinition.ROLE_APPLICATION) {
return false;
}
// At this point, it's a top-level override (probably XML), just having been parsed
// before configuration class processing kicks in...
if (this.registry instanceof DefaultListableBeanFactory &&
!((DefaultListableBeanFactory) this.registry).isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
beanName, "@Bean definition illegally overridden by existing bean definition: " + existingBeanDef);
}
if (logger.isDebugEnabled()) {
logger.debug(String.format("Skipping bean definition for %s: a definition for bean '%s' " +
"already exists. This top-level bean definition is considered as an override.",
beanMethod, beanName));
}
return true;
}
进入本类的isOverriddenByExistingDefinition(),判断是否重复扫描的情况:
protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) {
if (!this.registry.containsBeanDefinition(beanName)) {
return false;
}
BeanDefinition existingBeanDef = this.registry.getBeanDefinition(beanName);
// Is the existing bean definition one that was created from a configuration class?
// -> allow the current bean method to override, since both are at second-pass level.
// However, if the bean method is an overloaded case on the same configuration class,
// preserve the existing bean definition.
// ConfigurationClassBeanDefinition是有@Bean注解方法解析后的BeanDefiniton,
// 如果@Bean对应的beanName已经存在BeanDefinition,那么则把此BeanDefinition的isFactoryMethodUnique设置为false
// 后续根据此BeanDefinition取创建Bean时,就知道不止一个
if (existingBeanDef instanceof ConfigurationClassBeanDefinition) {
ConfigurationClassBeanDefinition ccbd = (ConfigurationClassBeanDefinition) existingBeanDef;
if (ccbd.getMetadata().getClassName().equals(
beanMethod.getConfigurationClass().getMetadata().getClassName())) {
if (ccbd.getFactoryMethodMetadata().getMethodName().equals(ccbd.getFactoryMethodName())) {
ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName());
}
return true;
}
else {
return false;
}
}
// A bean definition resulting from a component scan can be silently overridden
// by an @Bean method, as of 4.2...
// ScannedGenericBeanDefinition是扫描后得到的BeanDefinition
if (existingBeanDef instanceof ScannedGenericBeanDefinition) {
return false;
}
// Has the existing bean definition bean marked as a framework-generated bean?
// -> allow the current bean method to override it, since it is application-level
if (existingBeanDef.getRole() > BeanDefinition.ROLE_APPLICATION) {
return false;
}
// At this point, it's a top-level override (probably XML), just having been parsed
// before configuration class processing kicks in...
if (this.registry instanceof DefaultListableBeanFactory &&
!((DefaultListableBeanFactory) this.registry).isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
beanName, "@Bean definition illegally overridden by existing bean definition: " + existingBeanDef);
}
if (logger.isDebugEnabled()) {
logger.debug(String.format("Skipping bean definition for %s: a definition for bean '%s' " +
"already exists. This top-level bean definition is considered as an override.",
beanMethod, beanName));
}
return true;
}
- @Bean注解的Bean会覆盖@Component注解的;
- 如果都是@Bean注解的,覆盖;
- @Component注解重复了,报错。
前面的方法扫描和增强都做完了,得到了许多BeanDefinition,但是Bean的实例化对象还没生成,@Bean注解对应的方法还没调用,它是在创建Bean,实例化的时候,推断构造方法那儿才会调用。
2. postProcessBeanFactory()
接着看ConfigurationClassPostProcessor类的另外一个方法postProcessBeanFactory(),这是BeanFactoryPostProcessor接口的方法,该接口相当于BeanFactory的后置处理器,这里进行了重写了该方法,对有@Configuration注解的类生成代理:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
// 对于加@Configuration注解的配置类,CGLIB代理,字节码增强
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
进入enhanceConfigurationClasses()方法:
所属类:org.springframework.context.annotation.ConfigurationClassPostProcessor
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
// 遍历,根据beanName找出配置类
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
MethodMetadata methodMetadata = null;
if (beanDef instanceof AnnotatedBeanDefinition) {
methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
}
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
// Configuration class (full or lite) or a configuration-derived @Bean method
// -> resolve bean class at this point...
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
// 如果没有加载的话就去加载类
if (!abd.hasBeanClass()) {
try {
abd.resolveBeanClass(this.beanClassLoader);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
// 判断前面解析配置类得到的configClassAttr属性是否为full,如果是,则加入configBeanDefs容器
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
logger.info("Cannot enhance @Configuration bean definition '" + beanName +
"' since its singleton instance has been created too early. The typical cause " +
"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
"return type: Consider declaring such methods as 'static'.");
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
return;
}
// 对属性为full的配置类,生成代理类,并设置到BeanDefinition中
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);
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.getBeanClass();
// 生成配置类的代理对象
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
beanDef.setBeanClass(enhancedClass);
}
}
}
进入enhance()方法:
所属类:org.springframework.context.annotation.ConfigurationClassEnhancer
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Ignoring request to enhance %s as it has " +
"already been enhanced. This usually indicates that more than one " +
"ConfigurationClassPostProcessor has been registered (e.g. via " +
"<context:annotation-config>). This is harmless, but you may " +
"want check your configuration and remove one CCPP if possible",
configClass.getName()));
}
return configClass;
}
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
if (logger.isTraceEnabled()) {
logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
configClass.getName(), enhancedClass.getName()));
}
return enhancedClass;
}
看本类的createClass()方法:
private Class<?> createClass(Enhancer enhancer) {
Class<?> subclass = enhancer.createClass();
// Registering callbacks statically (as opposed to thread-local)
// is critical for usage in an OSGi environment (SPR-5932)...
Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
return subclass;
}
使用动态代理进行回调:
// The callbacks to use. Note that these callbacks must be stateless.
private static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(),
new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE
}
BeanMethodInterceptor是ConfigurationClassEnhancer的内部类,会执行BeanMethodInterceptor拦截器类的intercept()方法:
private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
/**
* Enhance a {@link Bean @Bean} method to check the supplied BeanFactory for the
* existence of this bean object.
* @throws Throwable as a catch-all for any exception that may be thrown when invoking the
* super implementation of the proxied method i.e., the actual {@code @Bean} method
*/
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// Determine whether this bean is a scoped-proxy
if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
beanName = scopedBeanName;
}
}
// To handle the case of an inter-bean method reference, we must explicitly check the
// container for already cached instances.
// First, check to see if the requested bean is a FactoryBean. If so, create a subclass
// proxy that intercepts calls to getObject() and returns any cached bean instance.
// This ensures that the semantics of calling a FactoryBean from within @Bean methods
// is the same as that of referring to a FactoryBean within XML. See SPR-6602.
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);
}
}
// 如果代理对象执行的方法是正在创建Bean的工厂方法,执行对应的方法得到对象作为Bean
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
// The factory is calling the bean method in order to instantiate and register the bean
// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
// create the bean instance.
if (logger.isInfoEnabled() &&
BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
"assignable to Spring's BeanFactoryPostProcessor interface. This will " +
"result in a failure to process annotations such as @Autowired, " +
"@Resource and @PostConstruct within the method's declaring " +
"@Configuration class. Add the 'static' modifier to this method to avoid " +
"these container lifecycle issues; see @Bean javadoc for complete details.",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
}
// 注意这里传入的是代理对象,相当于执行目标对象的方法
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
// 如果代理对象执行的方法不是正在创建Bean的方法,那就直接根据方法的name去Spring容器中获取(getBean()方法)
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
注意:如果有@Configuration注解的配置类里面存在@Bean注解的方法,在实例化执行invoke()方法时会通过代理对象执行方法,例如:
@Configuration
public class ConverterConfig {
@Bean
public UserService userService(){
kieasar();
return new UserService();
}
@Bean
public Kieasar kieasar() {
return new Kieasar();
}
}
上面的例子中,ConverterConfig的代理类在执行userService()方法会先进行判断,看是否为创建Bean的方法,如果是,则进行创建UserService的实例,相当于执行目标对象的方法,就会进入cglibMethodProxy.invokeSuper(),调用被代理对象的方法。
然后,代理对象接着执行userService()里面的kieasar()方法时,虽然该方法加了@Bean注解,但此时正在执行的是创建userService实例的userService()方法,所以isCurrentlyInvokedFactoryMethod()结果为false,会执行最后一行resolveBeanReference(),执行getBean()方法,根据方法的名字kieasar去容器中获取Kieasar对象的实例。
但是,Spring在创建Kieasar这个Bean时,如果当前执行的方法正好是kieasar()方法(也就是创建Kieasar实例的方法),此时isCurrentlyInvokedFactoryMethod()结果为true,执行cglibMethodProxy.invokeSuper(),即被代理对象的方法。
ConfigurationClassPostProcessor类的解析流程图:
最后,总结一下ConfigurationClassPostProcessor类的解析过程:
1. 在启动Spring时,需要传入一个ScanBean.class给ApplicationContext,ApplicationContext会根据ScanBean类封装为一个BeanDefinition,我们把它称为配置类BeanDefinition。
2. ConfigurationClassPostProcessor会把配置类BeanDefinition(ScanBean)取出来。
3. 构造一个ConfigurationClassParser用来解析配置类BeanDefinition,并且会生成一个配置类对象ConfigurationClass。
4. 如果配置类上存在@Component注解,那么解析配置类中的内部类(这里有递归,如果内部类也是配置类的话)。
5. 如果配置类上存在@PropertySource注解,那么则解析该注解,并得到PropertySource对象,并添加到environment中去。
6. 如果配置类上存在@ComponentScan注解,那么则解析该注解,进行扫描,扫描得到一系列的BeanDefinition对象,然后判断这些BeanDefinition是不是也是配置类BeanDefinition(只要存在@Component注解就是配置类,所以基本上扫描出来的都是配置类),如果是则继续解析该配置类,(也有递归),并且会生成对应的ConfigurationClass。
7. 如果配置类上存在@Import注解,那么则判断Import的类的类型:
- 如果是ImportSelector,那么调用执行selectImports方法得到类名,然后在把这个类当做配置类进行解析,(也是递归);
- 如果是ImportBeanDefinitionRegistrar,那么则生成一个ImportBeanDefinitionRegistrar实例对象,并添加到配置类对象中(ConfigurationClass)的importBeanDefinitionRegistrars属性中;
8. 如果配置类上存在@ImportResource注解,那么则把导入进来的资源路径存在配置类对象中的importedResources属性中。
9. 如果配置类中存在@Bean的方法,那么则把这些方法封装为BeanMethod对象,并添加到配置类对象中的beanMethods属性中。
10. 如果配置类实现了某些接口,则看这些接口内是否定义了@Bean注解的方法。
11. 如果配置类有父类,则把父类当做配置类进行解析。
12. ScanBean配置类会对应一个ConfigurationClass,同时在解析的过程中也会生成另外的一些ConfigurationClass,接下来就利用reader来进一步解析ConfigurationClass:
- 如果ConfigurationClass是通过@Import注解导入进来的,则把这个类生成一个BeanDefinition,同时解析这个类上@Scope、@Lazy等注解信息,并注册BeanDefinition;
- 如果ConfigurationClass中存在一些BeanMethod,也就是定义了一些@Bean,那么则解析这些@Bean,并生成对应的BeanDefinition,并注册;
- 如果ConfigurationClass中导入了一些资源文件,比如xx.xml,那么则解析这些xx.xml文件,得到并注册BeanDefinition;
- 如果ConfigurationClass中导入了一些ImportBeanDefinitionRegistrar,那么则执行对应的registerBeanDefinitions进行BeanDefinition的注册。