@Configuration注解加载过程
@Configuration注解加载过程
一、注解加载过程分析
-
启动类调用main方法,其中调用SpringApplicationBuilder的run方法
public static void main(String[] args) { new SpringApplicationBuilder(ElawApplication.class).web(true).run(args); }
-
run方法中使用AtomicBoolean running标志来记录是否已经在启动中,若未启动则进入同步代码块调用SpringApplication类的run方法进行构造ConfigurableApplicationContext上下文对象
-
SpringApplication的run方法中调用自身的createApplicationContext来创建对象
-
createApplicationContext方法根据webEnvironment来判断生成哪个上下文对象,webEnvironment用于标识是否为web应用,在默认情况下,如果是Web应用,则会创建AnnotationConfigEmbeddedWebApplicationContext类的对象;否则会创建AnnotationConfigApplicationContext类的对象;而 webEnvironment 这个变量是由项目的classpath下是否存在javax.servlet.Servlet或者org.springframework.web.context.ConfigurableWebApplicationContext,如果存在其中的一个,则为true;否则为false。
-
以AnnotationConfigApplicationContext为源码示例,构造方法中会调用AnnotatedBeanDefinitionReader的构造方法来实例化注解的BeanDefinition。
-
在AnnotatedBeanDefinitionReader构造方法中会调用自身的另一个带有环境对象的构造函数,环境对象使用getOrCreateEnvironment方法来获取,
在该构造函数中会调用AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)来手动创建(也就是硬编码)注解对应的PostProcessor。
其中,这些PostProcessor的类路径都是在代码中写死的,如果容器中不存在该PostProcessor的BeanDefinition,则手动创建并加入到容器中,
二、Configuration注解详解
1. 注解作用:
@Configuration标识的类有这些特性:可以声明多个@Bean方法,且在运行时被spring容器处理来生成BeanDefinition。@Configuration类是被AnnotationConfigWebApplicationContext启动(bootstrap)处理流程的。
2. 源码解析:
ConfigurationClass: 专门表示@Configuration class。存储解析@Configuration class的信息
ConfigurationClassPostProcessor: 专门用于处理@Configuration class的BeanDefinitoinRegistryPostProcessor(BeanFactoryPostProcessor子类)
AnnotationConfigUtils :专门注册BeanPostProcessor和BeanFactoryPostProcessor到spring容器
3. PostProcessorRegistrationDelegate解析过程:
Configuration注解的核心作用组件是ConfigurationClassPostProcessor,它是BeanFactoryPostProcessor类和BeanDefinitoinRegistryPostProcessor类型的子类。BeanFactoryPostProcessor实现了**AbstractApplicationContext's post-processor handling
**技术规范,在项目启动时,便会进行扫描处理,这个逻辑的入口在PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()方法
,代码如下:
class PostProcessorRegistrationDelegate {
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<String>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
new LinkedList<BeanDefinitionRegistryPostProcessor>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryPostProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
registryPostProcessors.add(registryPostProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registryPostProcessors.addAll(priorityOrderedPostProcessors);
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(beanFactory, orderedPostProcessors);
registryPostProcessors.addAll(orderedPostProcessors);
invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
registryPostProcessors.add(pp);
processedBeans.add(ppName);
pp.postProcessBeanDefinitionRegistry(registry);
reiterate = true;
}
}
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(beanFactory, orderedPostProcessors);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(beanFactory, orderedPostProcessors);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(beanFactory, internalPostProcessors);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
private static void sortPostProcessors(ConfigurableListableBeanFactory beanFactory, List<?> postProcessors) {
Comparator<Object> comparatorToUse = null;
if (beanFactory instanceof DefaultListableBeanFactory) {
comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
}
if (comparatorToUse == null) {
comparatorToUse = OrderComparator.INSTANCE;
}
Collections.sort(postProcessors, comparatorToUse);
}
/**
* Invoke the given BeanDefinitionRegistryPostProcessor beans.
*/
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
/**
* Invoke the given BeanFactoryPostProcessor beans.
*/
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
/**
* Register the given BeanPostProcessor beans.
*/
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
}
}
/**
* BeanPostProcessor that logs an info message when a bean is created during
* BeanPostProcessor instantiation, i.e. when a bean is not eligible for
* getting processed by all BeanPostProcessors.
*/
private static class BeanPostProcessorChecker implements BeanPostProcessor {
private static final Log logger = LogFactory.getLog(BeanPostProcessorChecker.class);
private final ConfigurableListableBeanFactory beanFactory;
private final int beanPostProcessorTargetCount;
public BeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory, int beanPostProcessorTargetCount) {
this.beanFactory = beanFactory;
this.beanPostProcessorTargetCount = beanPostProcessorTargetCount;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean != null && !(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) &&
this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
if (logger.isInfoEnabled()) {
logger.info("Bean '" + beanName + "' of type [" + bean.getClass() +
"] is not eligible for getting processed by all BeanPostProcessors " +
"(for example: not eligible for auto-proxying)");
}
}
return bean;
}
private boolean isInfrastructureBean(String beanName) {
if (beanName != null && this.beanFactory.containsBeanDefinition(beanName)) {
BeanDefinition bd = this.beanFactory.getBeanDefinition(beanName);
return RootBeanDefinition.ROLE_INFRASTRUCTURE == bd.getRole();
}
return false;
}
}
/**
* {@code BeanPostProcessor} that detects beans which implement the {@code ApplicationListener}
* interface. This catches beans that can't reliably be detected by {@code getBeanNamesForType}
* and related operations which only work against top-level beans.
*
* <p>With standard Java serialization, this post-processor won't get serialized as part of
* {@code DisposableBeanAdapter} to begin with. However, with alternative serialization
* mechanisms, {@code DisposableBeanAdapter.writeReplace} might not get used at all, so we
* defensively mark this post-processor's field state as {@code transient}.
*/
private static class ApplicationListenerDetector
implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {
private static final Log logger = LogFactory.getLog(ApplicationListenerDetector.class);
private transient final AbstractApplicationContext applicationContext;
private transient final Map<String, Boolean> singletonNames = new ConcurrentHashMap<String, Boolean>(256);
public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (this.applicationContext != null && beanDefinition.isSingleton()) {
this.singletonNames.put(beanName, Boolean.TRUE);
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (this.applicationContext != null && bean instanceof ApplicationListener) {
// potentially not detected as a listener by getBeanNamesForType retrieval
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
// singleton bean (top-level or inner): register on the fly
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
}
else if (flag == null) {
if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
// inner bean with other scope - can't reliably process events
logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
"but is not reachable for event multicasting by its containing ApplicationContext " +
"because it does not have singleton scope. Only top-level listener beans are allowed " +
"to be of non-singleton scope.");
}
this.singletonNames.put(beanName, Boolean.FALSE);
}
}
return bean;
}
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) {
if (bean instanceof ApplicationListener) {
ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();
multicaster.removeApplicationListener((ApplicationListener<?>) bean);
multicaster.removeApplicationListenerBean(beanName);
}
}
@Override
public boolean requiresDestruction(Object bean) {
return (bean instanceof ApplicationListener);
}
}
}
该方法会处理所有的BeanFactoryPostProcessor类型对象,但是通过优先级来规定先后处理顺序。这个优先级顺序会根据以下两个条件来判断:
a)BeanDefinitionRegistryPostProcessor类型和BeanFactoryPostProcessor类型
b)PriorityOrdered和Ordered
而ConfigurationClassPostProcessor同时实现了BeanDefinitionRegistryPostProcessor和PriorityOrdered接口,所以它得到最优先处理的机会,在代码流程中,首先会获取所有BeanDefinitionRegistryPostProcessor类型的beanName;
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
然后使用isTypeMatch方法进行查找,此时ConfigurationClassPostProcessor正好满足条件,则根据beanName从spring容器中获取ConfigurationClassPostProcessor实例。
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
接着调用invokeBeanDefinitionRegistryPostProcessors方法将@Configuration类生成BeanDefinition,此时的BeanDefinition.Class为原类class对象;
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
/**
* Invoke the given BeanDefinitionRegistryPostProcessor beans.
*/
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
/**
* ConfigurationClassPostProcessor class
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
processConfigBeanDefinitions(registry);
}
此时ConfigurationClassPostProcessor实例会将BeanDefinition.beanClass生成proxy代理类;
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
4. @Configuration class过程解析
下面的方法就是解析@Configuration class的核心逻辑了。解析过程可以总结分三步:
ConfigurationClassPostProcessor class
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)){
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));//(1)
}
}
··· 排序等
s
// 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 {
parser.parse(candidates); //(2)
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
// Read the model and create bean definitions based on its content
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
this.reader.loadBeanDefinitions(configClasses); //(3)
}
while (!candidates.isEmpty());
··· ···
}
step1: 获取候选者
从spring容器拿到所有的beanDefinitionNames,然后遍历验证获得候选者,验证的依据是class metadata是否含有@Configuration注解,从下面我们可知,此时,beanDefinitionNames中只有consumerFeignApp
符合条件。所以候选者就是consumerFeignApp及他的beanDefinition
step2: 通过候选者获取ConfigurationClass
找到了候选者,下面就对候选者进行解析,解析的全部功能和逻辑都集中在ConfigurationClassParser类中,看名称可知,这个类专业解析@Configuration类。
ConfigurationClassParser class
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
...
}
this.deferredImportSelectorHandler.process();
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
// 评估标识@Configuration的类是否满足条件去加载,这是条件注解@ConditionalXXX起的作用
// 实际开发中,我们可以依据这个功能实现灵活的加载配置(如让谁加载进来,不让谁加载进来^_^)
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
// Recursively process the configuration class and its superclass hierarchy.
SourceClass sourceClass = asSourceClass(configClass);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
// 所有加载的@Configuration类都会转为ConfigurationClass放入这个map中
this.configurationClasses.put(configClass, configClass);
}
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass){
// 为了集中说明意图,隐藏了代码
// Recursively process any member (nested) classes first
// Process any @PropertySource annotations
// Process any @ComponentScan annotations
for (AnnotationAttributes componentScan : componentScans) {
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
if () {
// 进入递归调用
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
// Process any @Import annotations
// Process any @ImportResource annotations
// Process individual @Bean methods
// Process default methods on interfaces
// Process superclass, if any
// No superclass -> processing is complete
return null;
}
如上方法整体的逻辑为对ConfigurationClass和SourceClass解析,检查他们有没有@ComponentScan,@Import,@Bean methods,@ImportResource,@PropertySource这些注解,如果有,分别对其解析,解析后的结果放入ConfigurationClass的各属性中
各个注解的属性值中可能又包含@Configuration注解,又要对包含的@Configuration注解进行解析,这样形成了递归,所以解析过程中有三个方法形成了三角递归调用的逻辑,
这一步会将我们项目中定义的@Configuration类都加载进来,你可能有疑问,难道项目中我们自己定义的@Configuration类都是靠递归加载进来的?答案当然是NO,请注意@ComponentScan注解,这个注解的解析器很厉害,它把所有的标识@Component注解的class加载进来,而@Configuration,@RestController,@Service,@Repository等都包含@Component,所有这些注解的class都会加载进来形成BeanDefinition存入spring 容器(解析过程详见ComponentScanAnnotationParser)。说回来,对于@ComponentScan解析器加载进来的BeanDefinitoin,会进行时@Configuration进行过滤,从而得到@Configuration类,再次调用parse()方法,这时体现出三角递归调用了。此时,项目中所有我们自定义的@Configuration类都获取到了
step3: 解析每个ConfigurationClass
step2中对@Configuration类的@Import,@Bean methods,@ImportResource进行解析,解析的结果放入ConfigurationClass对象的importBeanDefinitionRegistrars,beanMethods,importedResources,metadata等属性。
所以,step2将@Configuration类的解析结果都放入了ConfigurationClass对象,即ConfigurationClass对象包装了@Configuration类的所有信息。
回到ConfigurationClassPostProcessor.processConfigBeanDefinitions()方法(3)处,现在,我们解析ConfigurationClass,而解析ConfigurationClass过程由ConfigurationClassBeanDefinitionReader类负责的
ConfigurationClassBeanDefinitionReader class
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
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;
}
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
看loadBeanDefinitionsForConfigurationClass()方法,方法主要功能为对ConfigurationClass的beanMethods,importedResources,importBeanDefinitionReistrars属性进行解析,为什么要对这三个属性进行解析呢,看看这三个其@Import,@Bean methods,@ImportResource的用法
@Import(DispatcherServletConfiguration.class)
@ImportResource("classpath:/com/acme/database-config.xml")
protected static class DispatcherServletRegistrationConfiguration {
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
public DispatcherServletRegistrationBean dispatcherServletRegistration(){
...
}
}
可以看到,这三个注解的属性值都是类或者配置文件或者加载文件的类,所以,需要解析,从而将解析到的.class文件转化为BeanDefinition放入spring容器。
5. @Configuration类的cglib代理类实例化分析
由于@Configuration注解的都是类,而非接口,所有这里使用的是cglib代理技术,ConfigurationClassEnhancer包装了cglib。这里我们实际工作中可以直接复用ConfigurationClassEnhancer满足我们生成代理类的场景
实现自BeanFactoryPostProcessor.postProcessBeanFactory
ConfigurationClassPostProcessor class
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 生成代理
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
ConfigurationClassPostProcessor.ConfigurationClassEnhancer class
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
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.resolveBeanClass(this.beanClassLoader);
if (configClass != null) {
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
beanDef.setBeanClass(enhancedClass);
}
}
}
}
ConfigurationClassPostProcessor.ConfigurationClassEnhancer class
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
return configClass;
}
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
return enhancedClass;
}
普普通通搬砖: rehash时,旧hash表还会新增吗?
woshishe: dnjd
Love_you_for_ever: 引用「@Override protected void doHandleMessage(Messag」 这个
Love_you_for_ever: @Override protected void doHandleMessage(Message message) { this.publishEvent(new RedisKeyExpiredEvent(message.getBody())); 第4个栗子这样对么????
twenty_twoONE: 写的很详细,真棒