@Component及其衍生注解:@Configuration、@Controller、@Service、@Repository标记的类,被Spring IOC扫描到后,即可被容器管理起来。其原理基本涵盖在AnnotationConfigApplicationContext构造函数体的三行代码里。
public AnnotationConfigApplicationContext(String... basePackages) {this();scan(basePackages);refresh();
}
1. this()
这个无参构造方法做了三件事情:
- 首先创建bean工厂,实际上是在父类GenericApplicationContext的构造器里完成的
public GenericApplicationContext() {this.beanFactory = new DefaultListableBeanFactory();
}
- 然后初始化reader和scanner,这两个类就是AnnotationConfigApplicationContext类中的成员变量,作用是相同的,都是用来注册BeanDefinition对象,只不过场景不同
public AnnotationConfigApplicationContext() {
// 生成并注册5个BeanDefinition
// 1.ConfigurationClassPostProcessor
// 2.AutowiredAnnotationBeanPostProcessor
// 3.CommonAnnotationBeanPostProcessor
// 4.EventListenerMethodProcessor
// 5.DefaultEventListenerFactorythis.reader = new AnnotatedBeanDefinitionReader(this);
// spring提供api用来动态扫描注解
// 一般供扩展spring的时候用,内部扫描也是通过它this.scanner = new ClassPathBeanDefinitionScanner(this);
}
AnnotatedBeanDefinitionReader用于解析单个类或一组类的注解,并将其转换为相应的BeanDefinition对象。它通常用于编程式地注册bean定义,即在代码中显式地调用AnnotatedBeanDefinitionReader的方法来注册bean定义。
ClassPathBeanDefinitionScanner则用于在类路径下扫描指定的包,查找带有特定注解的类,并将其转换为相应的BeanDefinition对象。它通常用于自动化地注册bean定义,即在Spring容器启动时自动扫描指定包下的类,并将其转换为bean定义。
总的来说,AnnotatedBeanDefinitionReader适用于手动注册bean定义,上述5个Spring提供的类就是通过reader编程试注入的,而ClassPathBeanDefinitionScanner适用于自动化注册bean定义。
继续查看AnnotatedBeanDefinitionReader构造方法,上述5个类即通过AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)注册到beanDefinitionMap中
beanName | 类名 | 是否BeanDefinitionRegistryPostProcessor | 是否BeanFactoryPostProcessor | 是否BeanPostProcessor |
org.springframework.context.annotation.internalConfigurationAnnotationProcessor | ConfigurationClassPostProcessor | 是 | 是 | 是 |
org.springframework.context.annotation.internalAutowiredAnnotationProcessor | AutowiredAnnotationBeanPostProcessor | 否 | 否 | 是 |
org.springframework.context.annotation.internalCommonAnnotationProcessor | CommonAnnotationBeanPostProcessor | 否 | 否 | 是 |
org.springframework.context.event.internalEventListenerProcessor | EventListenerMethodProcessor | 否 | 是 | 否 |
org.springframework.context.event.internalEventListenerFactory | DefaultEventListenerFactory | 否 | 否 | 否 |
2. scan(basePackages)
在指定的基础包中执行扫描以查找组件类,这里是将扫描的类注册到beanDefinitionMap中。使用的正是上述创建scanner,该在创建的过程中,设置了一个@Component的注解类型过滤器,正是这个过滤器将扫描到的所有类过滤出标记了@Component及其衍生注解的类,逻辑如下:
//判断元信息读取器读取的类是否符合容器定义的注解过滤规则
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {// 如果读取的类的注解在排除注解过滤规则中,返回falsefor (TypeFilter tf : this.excludeFilters) {// 规则匹配功能if (tf.match(metadataReader, getMetadataReaderFactory())) {return false;}}// 如果读取的类的注解在包含的注解的过滤规则中,则返回true// 这里的includeFilters已经有了@Component过滤器for (TypeFilter tf : this.includeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return isConditionMatch(metadataReader);}}// 如果读取的类的注解既不在排除规则,也不在包含规则中,则返回falsereturn false;
}
3. refresh()
该方法是Spring应用上下文的核心方法,它负责完成Spring容器的初始化和刷新工作,由于篇幅有限,这里主要讲解与扫描和解析相关的方法:invokeBeanFactoryPostProcessors(beanFactory)
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// getBeanFactoryPostProcessors()得到的是程序员通过API直接添加的BeanFactory// 这里getBeanFactoryPostProcessors()90%情况都是返回空// 只有10%情况不为空【程序员通过API手动添加】PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}
}
接下来是invokeBeanFactoryPostProcessors方法了,该方法会调用在上述注入到beanDefinitionMap中的Spring内置的类BeanDefinitionRegistryPostProcessor及BeanFactoryPostProcessor对应的接口方法。整体逻辑可以分成两部分看:
- 先调用BeanDefinitionRegistryPostProcessor的子类;
- 再调用BeanFactoryPostProcessor的子类。
这里面会调用一个关键类ConfigurationClassPostProcessor,他会解析@Configuration标记的类,及类中@Bean方法,涉及到full和lite模式,由于篇幅有限,将在下一篇讲解。