文章目录
前言
该文主要是对其源码分析,以及单独调用记录
ClassPathBeanDefinitionScanner
一个bean定义扫描器,它检测类路径上的所有bean,并用给定的注册表(BeanFactory或ApplicationContext)注册相应的bean定义。
候选类别通过可配置的类型过滤器进行检测。
默认的过滤器包括用Spring的@Component、@Repository、@Service或@Controller构造型注释的类。
如果可用,还支持Java EE 6的@ManagedBean和@Named注解。
继承体系
- ClassPathBeanDefinitionScanner
- 继承了ClassPathScanningCandidateComponentProvider
开始
创建一个ClassPathBeanDefinitionScanner
,将AnnotationConfigApplicationContext
向下传递
- 创建 BeanDefinition 扫描器,可以用来扫描包或者类,继而转换为 BeanDefinition
- spring默认的扫描器其实不是这个scanner对象,而是在后面自己又重新new了一个ClassPathBeanDefinitionScanner
- spring在执行工程后置处理器 ConfigurationClassPostProcessor 时,去扫描包时会 new一个ClassPathBeanDefinitionScanner
- 这里的 scanne r仅仅是为了程序员可以手动调用 AnnotationConfigApplicationContext 对象的 scan 方法
public AnnotationConfigApplicationContext() {
//构建一个扫描器,用于扫描 Class 并且定义成 BeanDefinition
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
ClassPathBeanDefinitionScanner
接收了一个参数:AnnotationConfigApplicationContext (BeanDefinitionRegistry)
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
//穿
this(registry, true);
}
ClassPathBeanDefinitionScanner
- BeanDefinitionRegistry,这里其实可以理解为获取的是 beanFactory
- true 表示默认的过筛选器
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
//注意这个方法是 获取或者创建,其实这个 StandardEnvironment 是在 AnnotatedBeanDefinitionReader 的时候已经创建了,所以这次是去获取
this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}
ClassPathBeanDefinitionScanner
接收了三个参数:
-
BeanDefinitionRegistry,这里其实可以理解为获取的是 beanFactory
-
true 表示默认的过筛选器
-
Environment(StandardEnvironment)
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment) {
this(registry, useDefaultFilters, environment,
(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}
ClassPathBeanDefinitionScanner
- BeanDefinitionRegistry,这里其实可以理解为获取的是 beanFactory
- true 表示默认的过筛选器
- Environment(StandardEnvironment)
- ResourceLoader(AnnotationConfigApplicationContext)
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
// ClassPathBeanDefinitionScanner 继承了 ClassPathScanningCandidateComponentProvider
super();
this.registry = registry;
// 存在默认的筛选器... 这里传递过来的就是ture....
if (useDefaultFilters) {
// 主要关注的是整个方法,
registerDefaultFilters();
}
//设置环境
setEnvironment(environment);
//设置资源的加载器
setResourceLoader(resourceLoader);
}
调用registerDefaultFilters()
那其实可以理解 includeFilters 和 excludeFilters的参数了
- includeFilters 就是我们主要定义这些注解就能被 spring 扫描到
- excludeFilters 就是我们如果定义了这些注解就不能被 spring 扫描到
private final List<TypeFilter> includeFilters = new LinkedList<>();
protected void registerDefaultFilters() {
// 注册 @Component 类型的过滤器,只要带有这个注解的bean定义都会被扫描,也包括包装这个注解的注解
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
//@ManagedBean 如果存在如果存在也会被扫描
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
} catch (ClassNotFoundException ex) {
}
try {
//@Named 如果存在也会被扫描
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
} catch (ClassNotFoundException ex) {
}
}
后言
通过源码分析我们知道了
- 在初始化的时候帮我们创建了: ClassPathBeanDefinitionScanner
- 创建了:StandardEnvironment
- 将这些
@Component
、@ManagedBean
、@Named
注解添加到集合当中,包括类型是一样的也会添加到容器中,例如:@Service
扩展阅读
简单来说不依托于AnnotationConfigApplicationContext
的运行,单独拿这一小块内容出来使用
@Component
public class ClassPathBeanDefinitionScannerContext {
public static void main(String[] args) {
// 创建 BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 创建扫描器
ClassPathBeanDefinitionScanner value = new ClassPathBeanDefinitionScanner(beanFactory);
// 这里需要注意不要使用 toString方法
value.scan(ClassPathBeanDefinitionScannerContext.class.getPackage().getName());
// 创建Bean
User bean = beanFactory.getBean(User.class);
System.out.println(bean);
}
}
@Component
class User {
}
流程图
后续文章
- 源码-1:ApplicationContext-1
- 源码-2:ApplicationContext-2
- 源码-3:ApplicationContext-3
- 源码-4:ApplicationContext-4