目录
AnnotationConfigWebApplicationContext 注解类
AnnotationConfigWebApplicationContext 注解类
AnnotationConfigWebApplicationContext 类继承自 AbstractRefreshableWebApplicationContext 类 实现了 AnnotationConfigRegistry 接口,所有此类作用主要是通过注解配置的形式实现对象读取,解析和注册;
//载入注解Bean定义资源
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
//为容器设置注解Bean定义读取器
AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
//为容器设置类路径Bean定义扫描器
ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);
//获取容器的Bean名称生成器
BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
//为注解Bean定义读取器和类路径扫描器设置Bean名称生成器
if (beanNameGenerator != null) {
reader.setBeanNameGenerator(beanNameGenerator);
scanner.setBeanNameGenerator(beanNameGenerator);
beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
}
//获取容器的作用域元信息解析器
ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
//为注解Bean定义读取器和类路径扫描器设置作用域元信息解析器
if (scopeMetadataResolver != null) {
reader.setScopeMetadataResolver(scopeMetadataResolver);
scanner.setScopeMetadataResolver(scopeMetadataResolver);
}
// 注册自定义注解类到读取器中
if (!this.annotatedClasses.isEmpty()) {
if (logger.isInfoEnabled()) {
logger.info("Registering annotated classes: [" +
StringUtils.collectionToCommaDelimitedString(this.annotatedClasses) + "]");
}
reader.register(this.annotatedClasses.toArray(new Class<?>[this.annotatedClasses.size()]));
}
if (!this.basePackages.isEmpty()) {
if (logger.isInfoEnabled()) {
logger.info("Scanning base packages: [" +
StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
}
scanner.scan(this.basePackages.toArray(new String[this.basePackages.size()]));
}
//获取容器定义的Bean定义资源路径
String[] configLocations = getConfigLocations();
//如果定位的Bean定义资源路径不为空
if (configLocations != null) {
for (String configLocation : configLocations) {
try {
//使用当前容器的类加载器加载定位路径的字节码类文件
Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader());
if (logger.isInfoEnabled()) {
logger.info("Successfully resolved class for [" + configLocation + "]");
}
reader.register(clazz);
}
catch (ClassNotFoundException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not load class for config location [" + configLocation +
"] - trying package scan. " + ex);
}
//如果容器类加载器加载定义路径的Bean定义资源失败
//则启用容器类路径扫描器扫描给定路径包及其子包中的类
int count = scanner.scan(configLocation);
if (logger.isInfoEnabled()) {
if (count == 0) {
logger.info("No annotated classes found for specified class/package [" + configLocation + "]");
}
else {
logger.info("Found " + count + " annotated classes in package [" + configLocation + "]");
}
}
}
}
}
}东方鲤鱼
解析: AnnotationConfigWebApplicationContext 类中实现了loadBeanDefinitions()方法,主要步骤,第一步给容器设置AnnotatedBeanDefinitionReader 读取器和ClassPathBeanDefinitionScanner 扫描器,接着获取bran名称生成器,判断是否为空,不为空就设置给bean定义读取器和bean定义扫描器;第二步 获取容器的作用域元信息解析器ScopeMetadataResolver,并判断是否为空设置,此对象用来解析@Scope注解;第三步判断自定义类是否为空,不为空进行注册 ,此处的reader.register() 方法是将自定义类以bean difinition 形式注册到容器中;第四步 如果自定义包扫描路径不为空注册到扫描器中;第五步 检查容器中资源路径的configLocations 是否为空,循环利用类加载反射拿到配置类 注册到容器中,如果容器类加载器加载定义路径的Bean定义资源失败 ,则启用容器类路径扫描器扫描给定路径包及其子包中的类;
AnnotatedBeanDefinitionReader : 用于 编程式注册 已注解 bean 的 方便适配器,需要提供 BeanDefinitionRegistry 类 构造对象,注册的是 BeanDefinitionRegisty 中 的 beanDefinition;该类 是 ClassPathBeanDefininationScanner 的 一个替代品,使用 相同的 注解策略但是只显示的注册类;
ClassPathBeanDefininationScanner : 一个 bean 定义的 扫描器 ,用于检查 classpath 下 符合条件的bean ,使用给定的记录器 BeanFactory 或者 ApplicationContext 注册 相关的 bean 定义;符合条件的 类 是 通过 配置 类型过滤器来侦测的,默认的过滤器包括 注解了 Spring 的 Component,Repository,Service,Controller 的 类,而且也支持 Java EE 6 的 ManagedBean 注解 和 JSR-330 的 Named 注解;
getAnnotatedBeanDefinitionReader(beanFactory) 方法 内部涉及的spring 六大后置处理器
org.springframework.context.annotation.internalConfigurationAnnotationProcessor : 内部管理 Configuration 注解处理器 的 bean 的 名称;即ConfigurationClassPostProcessor类;
org.springframework.context.annotation.internalAutowiredAnnotationProcessor:内部管理 Autowired 注解处理器 的 bean 的名称;即AutowiredAnnotationBeanPostProcessor 类;
org.springframework.context.annotation.internalRequiredAnnotationProcessor:内部管理 Required 注解处理器 的 bean 的名称;即RequiredAnnotationBeanPostProcessor
类;
org.springframework.context.annotation.internalCommonAnnotationProcessor:内部管理 JSR-250 注解处理器 的 bean 的名称;即CommonAnnotationBeanPostProcessor 类;
org.springframework.context.annotation.internalPersistenceAnnotationProcessor:内部管理 JPA 注解处理器 的 bean 的名称 , 没有使用 JPA类库,不会加载;即PersistenceAnnotationBeanPostProcessor类;
org.springframework.context.event.internalEventListenerProcessor:内部管理 @EventListener 注解 处理器 的 bean 的名称;即EventListenerMethodProcessor类;
org.springframework.context.event.internalEventListenerFactory:内部管理 EventListenerFactory 的 bean 的名称;即DefaultEventListenerFactory类;
register 注册注解类方式
我们先看读取器的register方法内部 找到doRegisterBean 方法如下
//Bean定义读取器向容器注册注解Bean定义类
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//根据指定的注解Bean定义类,创建Spring容器中对注解Bean的封装的数据结构
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
//========第一步===========================
//解析注解Bean定义的作用域,若@Scope("prototype"),则Bean为原型类型;
//若@Scope("singleton"),则Bean为单态类型
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
//为注解Bean定义设置作用域
abd.setScope(scopeMetadata.getScopeName());
//为注解Bean定义生成Bean名称
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//========第二步===========================
//处理注解Bean定义中的通用注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//如果在向容器注册注解Bean定义时,使用了额外的限定符注解,则解析限定符注解。
//主要是配置的关于autowiring自动依赖注入装配的限定条件,即@Qualifier注解
//Spring自动依赖注入装配默认是按类型装配,如果使用@Qualifier则按名称
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
//如果配置了@Primary注解,设置该Bean为autowiring自动依赖注入装//配时的首选
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
//如果配置了@Lazy注解,则设置该Bean为非延迟初始化,如果没有配置,
//则该Bean为预实例化
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
//如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一
//个autowiring自动依赖注入装配限定符,该Bean在进autowiring
//自动依赖注入装配时,根据名称装配限定符指定的Bean
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
//创建一个指定Bean名称的Bean定义对象,封装注解Bean定义类数据
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
//========第三步===========================
//根据注解Bean定义类中配置的作用域,创建相应的代理对象
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//========第四步===========================
//向IOC容器注册注解Bean类定义对象
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}东方鲤鱼
解析:首先第一步生成注解bean 的定义类 ,接着解析bean的作用域,并设置注解bean作用域和生成bean名称,第二步 使用AnnotationConfigUtils的processCommonDefinitionAnnotations方法处理注解Bean定义类中通用的注解,比如lazy.DependsOn,Description等通用注解,创建一个指定Bean名称的Bean定义对象,封装注解Bean定义类数据;第三步 根据注解bean 定义对象,生成对应的代理对象,第四步 向ioc容器中注册类定义对象,入参registry 对象就是bean定义注册器;
//将解析的BeanDefinitionHold注册到容器中
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
//获取解析的BeanDefinition的名称
String beanName = definitionHolder.getBeanName();
//向IOC容器注册BeanDefinition
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
//如果解析的BeanDefinition有别名,向容器为其注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}东方鲤鱼
scanner.scan() 扫描类的方式
ClassPathBeanDefinitionScanner 类是类路径扫描器,负责扫描解析,注册;
//调用类路径Bean定义扫描器入口方法
public int scan(String... basePackages) {
//获取容器中已经注册的Bean个数
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
//启动扫描器扫描给定包
doScan(basePackages);
// Register annotation config processors, if necessary.
//注册注解配置(Annotation config)处理器
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
//返回注册的Bean个数
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}东方鲤鱼
//类路径Bean定义扫描器扫描给定包及其子包
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
//创建一个集合,存放扫描到Bean定义的封装类
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
//遍历扫描所有给定的包
for (String basePackage : basePackages) {
//调用父类ClassPathScanningCandidateComponentProvider的方法
//扫描给定类路径,获取符合条件的Bean定义
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
//遍历扫描到的Bean
for (BeanDefinition candidate : candidates) {
//获取Bean定义类中@Scope注解的值,即获取Bean的作用域
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
//为Bean设置注解配置的作用域
candidate.setScope(scopeMetadata.getScopeName());
//为Bean生成名称
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
//如果扫描到的Bean不是Spring的注解Bean,则为Bean设置默认值,
//设置Bean的自动依赖注入装配属性等
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
//如果扫描到的Bean是Spring的注解Bean,则处理其通用的Spring注解
if (candidate instanceof AnnotatedBeanDefinition) {
//处理注解Bean中通用的注解,在分析注解Bean定义类读取器时已经分析过
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
//根据Bean名称检查指定的Bean是否需要在容器中注册,或者在容器中冲突
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
//根据注解中配置的作用域,为Bean应用相应的代理模式
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//向容器注册扫描到的Bean
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}东方鲤鱼
解析:对上下文中的配置通过类路径扫描器扫描到放到一个set 集合,循环这些类定义,对其作用域元数据进行判断,生成bean定义名称,然后设置自动注入的属性,如果扫描的不是注解bean 定义的类 设置默认值,如果是扫描类,则和上边注册的方式一样,解析通用注解;然后根据代理模式 创建代理完成向容器的注册;