原文地址:http://blog.****.net/jin5203344/article/details/78590111
在微服务大趋势下Springboot,Springcloud成为更多公司新项目技术框架的选型 ,Springboot简洁的基本零配置,很重要的一点是将以前通过xml方式配置bean转换为
通过@Configuration @Bean的方式来进行,今天主要分析下Spring是如何来实现对这两个注解进行处理的
通过Springboot的启动来跟踪分析容器的启动(这里只是简单的带过,后面会在springboot源码分析中,详细讲解),run方法具体实现如下:
-
public ConfigurableApplicationContext run(String... args) {
-
if (this.running.get()) {
-
// If already created we just return the existing context
-
return this.context;
-
}
-
configureAsChildIfNecessary(args);
-
if (this.running.compareAndSet(false, true)) {
-
synchronized (this.running) {
-
// 如果容器未启动,启动容器,装配资源
-
this.context = build().run(args);
-
}
-
}
-
return this.context;
-
}
-
public ConfigurableApplicationContext run(String... args) {
-
StopWatch stopWatch = new StopWatch();
-
stopWatch.start();
-
ConfigurableApplicationContext context = null;
-
FailureAnalyzers analyzers = null;
-
configureHeadlessProperty();
-
SpringApplicationRunListeners listeners = getRunListeners(args);
-
listeners.starting();
-
try {
-
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
-
args);
-
ConfigurableEnvironment environment = prepareEnvironment(listeners,
-
applicationArguments);
-
Banner printedBanner = printBanner(environment);//打印beanner
-
context = createApplicationContext();//创建默认的上下文
-
analyzers = new FailureAnalyzers(context);
-
prepareContext(context, environment, listeners, applicationArguments,
-
printedBanner);
-
refreshContext(context);// 刷新容器
-
afterRefresh(context, applicationArguments);
-
listeners.finished(context, null);
-
stopWatch.stop();
-
if (this.logStartupInfo) {
-
new StartupInfoLogger(this.mainApplicationClass)
-
.logStarted(getApplicationLog(), stopWatch);
-
}
-
return context;
-
}
-
catch (Throwable ex) {
-
handleRunFailure(context, listeners, analyzers, ex);
-
throw new IllegalStateException(ex);
-
}
-
}
重点关注refreshContext,在refreshContext中 就有第一篇中分析容器入口的refresh方法
-
private void refreshContext(ConfigurableApplicationContext context) {
-
refresh(context);
-
if (this.registerShutdownHook) {
-
try {
-
context.registerShutdownHook();
-
}
-
catch (AccessControlException ex) {
-
// Not allowed in some environments.
-
}
-
}
-
}
事实上 我们分析的入口依然是refresh这个核心方法,这里就不重复贴源码了,这是我们之前loadBeanDefinitions换成 AnnotationConfigWebApplicationContext 类

AnnotationBeanDefinitionReader 对应构造函数 为:
-
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);
-
}
可以看到 最后一行 注册AnnotationConfigProcessors,有什么用呢,接着看其实现:
-
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
-
BeanDefinitionRegistry registry, Object source) {
-
-
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
-
if (beanFactory != null) {
-
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
-
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
-
}
-
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
-
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
-
}
-
}
-
-
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
-
// 处理Configuration注解的 postProcessor
-
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));
-
}
-
// 处理autowired注解的 postProcessor
-
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));
-
}
-
// 处理required注解的 postProcessor
-
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
-
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
-
def.setSource(source);
-
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
-
}
-
-
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
-
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.
-
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));
-
}
-
-
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));
-
}
-
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;
-
}
这里我们只用关系,configuration注解的处理,实际是向容器中接入了 对Configuration注解的 处理类 ConfigurationClassPostProcessor,
那我们有个疑问,这个类什么时候会调用呢? 回到refresh方法中,有一行关键代码
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
方法内容比较多,这里就选取一个分支来说明下
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);
第一行:从工厂类中得到所有 BeanDefinitionRegistryPostProcessor类型的bean
第三——九行 循环判断添加到 需要处理的列表中
第十二行:执行具体需要处理的postProcessors
具体实现如下:
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
也就是循环调用postProcessor的 postProcessBeanDefinitionRegistry方法,而ConfigurationClassPostProcessor类的对应方法内部调用逻辑顺序
postProcessBeanDefinitionRegistry ——》 processConfigBeanDefinitions ——》
-
// Parse each @Configuration class
-
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);
-
parser.validate();
-
....
-
}while (!candidates.isEmpty());
从源码注释就能看出 是解析 @Configuration 注解的类 通过ConfigurationClassParser 来进行处理
parser ——》processConfigurationClass ——》doProcessConfigurationClass
-
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 注解
-
AnnotationAttributes componentScan = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ComponentScan.class);
-
if (componentScan != null && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
-
// The config class is annotated with @ComponentScan -> perform the scan immediately
-
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 necessary
-
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);
-
String[] resources = importResource.getAliasedStringArray("locations", ImportResource.class, sourceClass);
-
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 = sourceClass.getMetadata().getAnnotatedMethods(Bean.class.getName());
-
for (MethodMetadata methodMetadata : beanMethods) {
-
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
-
}
-
-
// 处理接口中默认方法
-
for (SourceClass ifc : sourceClass.getInterfaces()) {
-
beanMethods = ifc.getMetadata().getAnnotatedMethods(Bean.class.getName());
-
for (MethodMetadata methodMetadata : beanMethods) {
-
if (!methodMetadata.isAbstract()) {
-
// A default method or other concrete method on a Java 8+ interface...
-
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
-
}
-
}
-
}
-
-
// 处理父类
-
if (sourceClass.getMetadata().hasSuperClass()) {
-
String superclass = sourceClass.getMetadata().getSuperClassName();
-
if (!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;
-
}
其他注解的处理这里暂且不作分析,后面有机会再补上,有兴趣的读者可以自行查看源码学习,原理都差不多,解析到对于的信息添加到configClass中
可以看到通过解析@Bean注解,获取到所有带有@Bean注解的方法,创建对应的BeanMethod添加到configClass中,回到processConfigBeanDefinitions方法
this.reader.loadBeanDefinitions(configClasses);
通过configClasses加载bean定义
查看具体实现
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.removeImportingClassFor(configClass.getMetadata().getClassName());
return;
}
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// 循环加载 beanMethod
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
loadBeanDefinitionsForBeanMethod 字面意思 为beanMethod加载beanDefinition
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;
}
// Consider name and any aliases
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name")));
String beanName = (names.size() > 0 ? 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)?
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
return;
}
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
beanDef.setResource(configClass.getResource());
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
if (metadata.isStatic()) {
// static @Bean method
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
beanDef.setFactoryMethodName(methodName);
}
else {
// instance @Bean method
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 = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
String destroyMethodName = bean.getString("destroyMethod");
if (destroyMethodName != null) {
beanDef.setDestroyMethodName(destroyMethodName);
}
// Consider scoping
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
beanDef.setScope(attributes.getAliasedString("value", Scope.class, configClass.getResource()));
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.isDebugEnabled()) {
logger.debug(String.format("Registering bean definition for @Bean method %s.%s()",
configClass.getMetadata().getClassName(), beanName));
}
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
通过元数据以及相关信息 装配 注册beanDefinition