@Configuration源码讲解
示例
// ------------------------ 配置文件
@Configuration
public class SpringConfig {
@Bean
public Piano piano() {
return new Piano();
}
@Bean(name = "counter")
public Counter counter() {
return new Counter(12, "Shake it Off", piano());
}
}
// ------------------------ 测试
ApplicationContext annotationContext = new AnnotationConfigApplicationContext("xxxPackagePath");
Counter c = annotationContext.getBean("counter", Counter.class);
Assert.assertEquals("糊涂",c.getName()); //测试
AnnotationConfigApplicationContext
以上的代码非常简单, 一眼就能看出关键点就是这个AnnotationConfigApplicationContext类了.
而下面的AnnotationConfigApplicationContext构造函数中, 相信注释已经很清楚了, 这里我们关注的重点当然就是scan(basePackages);方法.至于其它两个方法:
this(); 主要是为了实例化自身的两个重要字段.
refresh(); 这个方法至关重要, 不过不是本文的重点. 所以直接略过.如果读者有兴趣, 可以参见本人下面给出的链接, 或者查阅《Spring源码深度解读》—— 作者在其书中对此方法进行了详尽的解读, 个人觉得还是很值得买一本的
public AnnotationConfigApplicationContext(String... basePackages) {
// 调用自身的构造函数
this();
// 扫描指定package下的bean
scan(basePackages);
// 调用基类AbstractApplicationContext中的refresh()方法.
refresh();
}
AnnotationConfigApplicationContext.scan 方法
public void scan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
// 这个scanner就是上文所说的由this()实例化的字段, 类型为 ClassPathBeanDefinitionScanner
this.scanner.scan(basePackages);
}
ClassPathBeanDefinitionScanner.scan 方法
public int scan(String... basePackages) {
// 统计扫描之前, 容器中的bean数量
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
// 关于这个方法, 请看本人的另外一遍博客 http://blog.csdn.net/lqzkcx3/article/details/78150513 中的第五小节及之后的内容.
doScan(basePackages);
// Register annotation config processors, if necessary.
// 所以这个才是本次关注的重心所在
// 默认情况下, this.includeAnnotationConfig 为true.所以默认情况下是一定会调用
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
// 返回本次扫描后新增的bean数量
return this.registry.getBeanDefinitionCount() - beanCountAtScanStart;
}
AnnotationConfigUtils.registerAnnotationConfigProcessors 方法
/**
* Register all relevant annotation post processors in the given registry.
*/
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相关的处理器ConfigurationClassPostProcessor
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、@Value、@Inject相关的处理器AutowiredAnnotationBeanPostProcessor
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相关的处理器RequiredAnnotationBeanPostProcessor
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));
}
//在支持JSR-250条件下注册javax.annotation包下注解处理器,包括@PostConstruct、@PreDestroy、@Resource注解等
// 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));
}
//支持jpa的条件下,注册org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor处理器,处理jpa相关注解
// 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));
}
// 以下这两个判断是我专门去4.3.11版本里复制过来的
// 增加@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));
}
// 注册支持@EventListener注解的处理器, 也就是DefaultEventListenerFactory实例了
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类
既然此次我们关注的重点是@Configuration, 目光当然就落在ConfigurationClassPostProcessor类上了, 观察其继承链, 鼎鼎大名的BeanFactoryPostProcessor赫然在目. 这个类的关键性就不在这里赘述了.
ConfigurationClassPostProcessor 继承链
所以Spring会回调这两个方法
postProcessBeanDefinitionRegistry(由BeanDefinitionRegistryPostProcessor接口定义)
postProcessBeanFactory(由BeanFactoryPostProcessor接口定义)
BeanDefinitionRegistryPostProcessor接口又继承自BeanFactoryPostProcessor; 依据注释, 前者所定义方法的被执行时机位于后者所定义方法之前.
// --------------------------- BeanDefinitionRegistryPostProcessor接口的实现
/**
* Derive further bean definitions from the configuration classes in the registry.
*/
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 向容器中注册一个 ImportAwareBeanPostProcessor 实例; 用于处理 ImportAware 接口标签
RootBeanDefinition iabpp = new RootBeanDefinition(ImportAwareBeanPostProcessor.class);
iabpp.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(IMPORT_AWARE_PROCESSOR_BEAN_NAME, iabpp);
// this.registriesPostProcessed 和 this.factoriesPostProcessed : 这两个类级字段用于确保本方法只被调用一次,
// 在结合下面的 postProcessBeanFactory 方法, 这两个字段的另外一个作用是确保 processConfigBeanDefinitions 方法只执行一次.
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called for this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called for this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
// --------------------------- BeanFactoryPostProcessor接口的实现
/**
* Prepare the Configuration classes for servicing bean requests at runtime
* by replacing them with CGLIB-enhanced subclasses.
*/
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called for 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);
}
enhanceConfigurationClasses(beanFactory);
}
通过观察上面必将被Spring框架回调的两个方法, 我们可以推测:
这两个方法必将被会调用, 且都只会被调用一次.
在执行顺序是 processConfigBeanDefinitions在先, 而enhanceConfigurationClasses在后.
processConfigBeanDefinitions方法
/**
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
Set<BeanDefinitionHolder> configCandidates = new LinkedHashSet<BeanDefinitionHolder>();
// 迭代现有容器中所有bean
for (String beanName : registry.getBeanDefinitionNames()) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 注意下面这个方法会向BeanDefinition类型的beanDef注入一个名ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE为的Attribute
// 返回true的条件是该beanDef代表的类被@Configuration或@Component或@Bean修饰
// @Configuration注解上有@Component所修饰, @Bean上可没有
if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
// 如果没有被任何被上述三注解所修饰的, 则中断接下来的处理, 直接返回.
if (configCandidates.isEmpty()) {
return;
}
// Detect any custom bean name generation strategy supplied through the enclosing application context
// 上面的官方注释已经很清楚了
SingletonBeanRegistry singletonRegistry = null;
if (registry instanceof SingletonBeanRegistry) {
singletonRegistry = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet && singletonRegistry.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
BeanNameGenerator generator = (BeanNameGenerator) singletonRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
// Parse each @Configuration class
// 构建一个专门处理@Configuration的类, 注意该类的访问级别也是 package
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
// 解析每个BeanDefinition
if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parser.parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parser.parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("Failed to load bean class: " + bd.getBeanClassName(), ex);
}
}
// 验证解析的成果
parser.validate();
// --------------------------------------------------------------
// 1. 在经过上面的parser.validate();之后, 代表基本解析工作完毕, 并且通过验证
// 2. 接下来要做的是提取解析的成果, 进行相应的处理, 例如将解析出来的BeanMethod(代表一个被@Bean标注的方法)集合注册进容器
// --------------------------------------------------------------
// Handle any @PropertySource annotations
// 处理上面的parse解析出来的@PropertySource信息
// @PropertySource注解的主要功能是引入配置文件,将配置的属性键值对与环境变量中的配置合并
// @PropertySources仅仅只是包含多个@PropertySource
Stack<PropertySource<?>> parsedPropertySources = parser.getPropertySources();
if (!parsedPropertySources.isEmpty()) {
if (!(this.environment instanceof ConfigurableEnvironment)) {
logger.warn("Ignoring @PropertySource annotations. " +
"Reason: Environment must implement ConfigurableEnvironment");
}
else {
MutablePropertySources envPropertySources = ((ConfigurableEnvironment)this.environment).getPropertySources();
while (!parsedPropertySources.isEmpty()) {
envPropertySources.addLast(parsedPropertySources.pop());
}
}
}
// Read the model and create bean definitions based on its content
// 创建一个用于加载Bean的reader
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.problemReporter, this.metadataReaderFactory,
this.resourceLoader, this.environment, this.importBeanNameGenerator);
}
// 1. 处理解析出来的被@Configuration注解的类信息(被@Configuration修饰的类相关的元数据被使用ConfigurationClass来承载)
// 2. 例如包括解析ConfigurationClass中的BeanMethod实例集合(每个BeanBeanMethod代表的是被@Bean修饰的方法,也就是一个Bean实例)
this.reader.loadBeanDefinitions(parser.getConfigurationClasses());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
// 不再赘述
if (singletonRegistry != null) {
if (!singletonRegistry.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
singletonRegistry.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
ConfigurationClassParser类
Parse each @Configuration class — 官方注释
访问级别级别为 package;
位于org.springframework.context.annotation package下
// Parse the specified {@link Configuration @Configuration} class.
public void parse(String className, String beanName) throws IOException {
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
// 注意这里使用ConfigurationClass进行了包装
// 即在Spring中每个ConfigurationClass代表一个被@Configuration修饰的配置类
processConfigurationClass(new ConfigurationClass(reader, beanName));
}
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
// 略过开始部分的代码
// Recursively process the configuration class and its superclass hierarchy.
do {
metadata = doProcessConfigurationClass(configClass, metadata);
}
while (metadata != null);
this.configurationClasses.add(configClass);
}
/**
* @return annotation metadata of superclass, {@code null} if none found or previously processed
*/
protected AnnotationMetadata doProcessConfigurationClass(ConfigurationClass configClass, AnnotationMetadata metadata) throws IOException {
//----------- 虽然看着比较多, 但还是比较清晰; 空格分开的段落之间, 彼此各自处理各自的内容
// recursively process any member (nested) classes first
processMemberClasses(metadata);
// process any @PropertySource annotations
AnnotationAttributes propertySource = MetadataUtils.attributesFor(metadata,
org.springframework.context.annotation.PropertySource.class);
if (propertySource != null) {
processPropertySource(propertySource);
}
// process any @ComponentScan annotations
// @ComponentScan定义自动扫描的包, 其最关键的方法为doScan方法,会注册BeanDefinition到容器中。
AnnotationAttributes componentScan = MetadataUtils.attributesFor(metadata, ComponentScan.class);
if (componentScan != null) {
// the config class is annotated with @ComponentScan -> perform the scan immediately
// 这里的this.componentScanParser, 其类型为ComponentScanAnnotationParser(访问级别也是package)
// 也就是说ComponentScanAnnotationParser负责了@ComponentScan的解析工作
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, metadata.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)) {
this.parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
}
}
// process any @Import annotations
// @Import注解可以配置需要引入的class
Set<Object> imports = new LinkedHashSet<Object>();
Set<Object> visited = new LinkedHashSet<Object>();
collectImports(metadata, imports, visited);
if (!imports.isEmpty()) {
processImport(configClass, metadata, imports, true);
}
// process any @ImportResource annotations
// @ImportResource的主要功能为引入资源文件。
if (metadata.isAnnotated(ImportResource.class.getName())) {
AnnotationAttributes importResource = MetadataUtils.attributesFor(metadata, ImportResource.class);
String[] resources = importResource.getStringArray("value");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// process individual @Bean methods
// 这里就是解析每个@Bean元信息的
// 一个BeanMethod代表一个被@Bean修饰的方法,也就是一个Bean实例
Set<MethodMetadata> beanMethods = metadata.getAnnotatedMethods(Bean.class.getName());
for (MethodMetadata methodMetadata : beanMethods) {
// 使用BeanMethod封装解析出来的结果
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// process superclass, if any
if (metadata.hasSuperClass()) {
String superclass = metadata.getSuperClassName();
if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// superclass found, return its annotation metadata and recurse
if (metadata instanceof StandardAnnotationMetadata) {
Class<?> clazz = ((StandardAnnotationMetadata) metadata).getIntrospectedClass();
return new StandardAnnotationMetadata(clazz.getSuperclass(), true);
}
else {
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(superclass);
return reader.getAnnotationMetadata();
}
}
}
// no superclass, processing is complete
return null;
}
ConfigurationClassBeanDefinitionReader类
这个类的访问级别也是 package.
/**
* Read a particular {@link ConfigurationClass}, registering bean definitions for the
* class itself, all its {@link Bean} methods
*/
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass) {
if (configClass.isImported()) {
// Register the {@link Configuration} class itself as a bean definition.
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
// 解读每个BeanMethod里的元数据, 将解析得到的bean注册进容器
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
}
enhanceConfigurationClasses方法
而原因就发生在 ConfigurationClassPostProcessor类的enhanceConfigurationClasses方法中.
其它暂时略.
Links
Last updated
Was this helpful?