Ioc容器——AnnotationConfigApplicationContext
1. Spring 官方文档
You should use an ApplicationContext
unless you have a good reason for not doing so, with GenericApplicationContext
and its subclass AnnotationConfigApplicationContext
as the common implementations for custom bootstrapping. These are the primary entry points to Spring’s core container for all common purposes: loading of configuration files, triggering a classpath scan, programmatically registering bean definitions and annotated classes, and (as of 5.0) registering functional bean definitions.
大致意思是说:
能使用
ApplicationContext
就不是用BeanFactory
。用GenericApplicationContext
及其子类AnnotationConfigAppliactionContext
作为自定义引导的常用实现。这几个是Spring核心容器的主要入口点,用于加载配置文件、触发类路径扫描、以编程的方式注册Bean定义和带注释的类,以及从5.0开始的注册功能性Bean定义。
2. AnnotationConfigApplicationContext源码
AnnotationConfigApplicationContext
是Spring3.0以后引入的类,用于处理Spring注解,使用AnnotationConfigApplicationContext
可以实现基于Java的配置类加载Spring的应用上下文,避免使用application.xml
进行配置。相比XML配置,更加便捷。
AnnotationConfigApplicationContext
继承于GenericApplicationContext
,而GenericApplicationContext
继承于BeanDefinitionRegistry
。Spring容器是通过BeanDefinition对象来表示Bean的,BeanDefinition
描述了Bean的相关信息。
BeanDefinitionRegistry
接口提供了向容器中注册、删除、获取BeanDefinition
对象的方法。简单来说就是BeanDefinitionRegistry
可以管理BeanDefinition
,也就是说AnnotationConfigApplicationContext
是管理Bean的重要类。
package org.springframework.context.annotation;
import java.util.function.Supplier;
import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
/**
* Bean读取器
*/
private final AnnotatedBeanDefinitionReader reader;
/**
* 类扫描器
*/
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
/**
* 创建一个AnnotationConfigApplicationContext,并再给定包路径下的BeanDefinitions进行扫描。
*/
public AnnotationConfigApplicationContext(String... basePackages) {
this();
//扫描指定包路径下的类
scan(basePackages);
//刷新上下文
refresh();
}
@Override
public void setEnvironment(ConfigurableEnvironment environment) {
super.setEnvironment(environment);
this.reader.setEnvironment(environment);
this.scanner.setEnvironment(environment);
}
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
this.reader.setBeanNameGenerator(beanNameGenerator);
this.scanner.setBeanNameGenerator(beanNameGenerator);
getBeanFactory().registerSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
}
public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
this.reader.setScopeMetadataResolver(scopeMetadataResolver);
this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
}
/**
* 按指定Bean配置类读取Bean
*/
public void register(Class<?>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.reader.register(annotatedClasses);
}
/**
* 扫描指定的包
*/
public void scan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
this.scanner.scan(basePackages);
}
/**
* 注册Bean
*/
public <T> void registerBean(Class<T> annotatedClass, Object... constructorArguments) {
registerBean(null, annotatedClass, constructorArguments);
}
public <T> void registerBean(@Nullable String beanName, Class<T> annotatedClass, Object... constructorArguments) {
this.reader.doRegisterBean(annotatedClass, null, beanName, null,
bd -> {
for (Object arg : constructorArguments) {
bd.getConstructorArgumentValues().addGenericArgumentValue(arg);
}
});
}
@Override
public <T> void registerBean(@Nullable String beanName, Class<T> beanClass, @Nullable Supplier<T> supplier,
BeanDefinitionCustomizer... customizers) {
this.reader.doRegisterBean(beanClass, supplier, beanName, null, customizers);
}
}
-
refresh
refresh方法在
AbstractApplicationContext
容器中实现,refresh()
方法的作用加载或者刷新当前的配置信息,如果已经存在spring容器,则先销毁之前的容器,重新创建spring容器,载入bean定义,完成容器初始化工作,所以可以看出AnnotationConfigApplicationContext
容器是通过调用其父类AbstractApplicationContext
的refresh()
函数启动整个IoC容器完成对Bean定义的载入。
3. BeanDefinitionRegistry
将定义 bean 的资源文件解析成
BeanDefinition
后需要将其注入容器中,这个过程由BeanDefinitionRegistry
来完成。
BeanDefinitionRegistry
继承了AliasRegistry
接口,其核心子类有三个:SimpleBeanDefinitionRegistry
、DefaultListableBeanFactory
、GenericApplicationContext
。
BeanDefinition
的注册接口,如RootBeanDefinition
和ChildBeanDefinition
。它通常由BeanFactories
实现,在 Spring 中已知的实现者为:DefaultListableBeanFactory
和GenericApplicationContext
。BeanDefinitionRegistry
是 Spring 的 Bean 工厂包中唯一封装BeanDefinition
注册的接口。
package org.springframework.beans.factory.support;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.AliasRegistry;
/**
* BeanDefinitionRegistry 接口定义了关于 BeanDefinition 注册、注销、查询等一系列的操作。
*/
public interface BeanDefinitionRegistry extends AliasRegistry {
//向注册表中注册一个新的BeanDefinition
void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
//移除注册表中已注册的BeanDefinition
void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
//从注册表中获取一个BeanDefinition的实例
BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
//判断是否包含BeanDefinition实例
boolean containsBeanDefinition(String var1);
//获取注册表中所有BeanDefinition实例的beanName标识
String[] getBeanDefinitionNames();
//返回注册表中BeanDefinition实例的数量
int getBeanDefinitionCount();
//beanName是否已经被占用
boolean isBeanNameInUse(String var1);
}
1. SimpleBeanDefinitionRegistry
SimpleBeanDefinitionRegistry
是BeanDefinitionRegistry
的一个简单实现,它还继承了SimpleAliasRegistry
,仅仅提供注册表的功能。
package org.springframework.beans.factory.support;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.SimpleAliasRegistry;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {
//使用ConcurrentHashMap来注册BeanDefinition
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(64);
public SimpleBeanDefinitionRegistry() {
}
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "'beanName' must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
this.beanDefinitionMap.put(beanName, beanDefinition);
}
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
if (this.beanDefinitionMap.remove(beanName) == null) {
throw new NoSuchBeanDefinitionException(beanName);
}
}
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (bd == null) {
throw new NoSuchBeanDefinitionException(beanName);
} else {
return bd;
}
}
public boolean containsBeanDefinition(String beanName) {
return this.beanDefinitionMap.containsKey(beanName);
}
public String[] getBeanDefinitionNames() {
return StringUtils.toStringArray(this.beanDefinitionMap.keySet());
}
public int getBeanDefinitionCount() {
return this.beanDefinitionMap.size();
}
public boolean isBeanNameInUse(String beanName) {
return this.isAlias(beanName) || this.containsBeanDefinition(beanName);
}
}
SimpleBeanDefinitionRegistry
的功能实现都是依赖于beanDefinitionMap
,简单粗暴。
2. DefaultListableBeanFactory
DefaultListableBeanFactory
继承于ConfigurableListableBeanFactory, BeanDefinitionRegistry
接口,一个基于BeanDefinition
元数据的完整的Bean工厂。同样使用ConcurrentHashMap
来存储注册的BeanDefinition
。
/**
* 注册表,key-beanName,value-BeanDefinition实例
*/
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
/**
* 所有beanName的集合
*/
private volatile List<String> beanDefinitionNames = new ArrayList(256);
- registerBeanDefinition()
注册BeanDefinition
的方法
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var8) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
}
}
BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
//beanDefinitionMap中不存在实例
if (existingDefinition != null) {
//....省略
this.beanDefinitionMap.put(beanName, beanDefinition);
}
//已经存在实例
else {
//检查factory's bean 是否开始创建
if (this.hasBeanCreationStarted()) {
Map var4 = this.beanDefinitionMap;
synchronized(this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
this.removeManualSingletonName(beanName);
}
} else {
//注册 BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || this.containsSingleton(beanName)) {
this.resetBeanDefinition(beanName);
}
}
4. AnnotatedBeanDefinitionReader
AnnotationConfigApplicationContext
注册BeanDefinition
是通过AnnotatedBeanDefinitionReader
类来实现的,调用的都是AnnotatedBeanDefinitionReader
的 doRegisterBean()
//完成bean配置类本身的解析和注册
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//先把实体类型转化成BeanDefinition类型
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//abd.getMetadata 获取BeanDefinition的元数据信息:注解信息、是否内部类、类Class基本信息
//conditionEvaluator.shouldskip 判断此类是否为配置类
//@Conditional装配条件判断是否需要跳过注册
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
//
abd.setInstanceSupplier(instanceSupplier);
//解析bean作用域(单例或者原型),如果有@Scope注解,则解析@Scope,没有则默认为singleton
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
//得到beanName,一般为首字母小写的类名
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//设定注解的默认值
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//解析qualifiers 若有此注解,则primary设置为true
if (qualifiers != null) {
//
for (Class<? extends Annotation> qualifier : qualifiers) {
//如果配置了@Primary注解,则设置当前的bean为制动装配autowired首选
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
//懒加载/延迟加载
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
//其他注解添加到abd结构中
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
//自定义定制信息(一般都不需要)
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
//根据beanName和bean定义信息封装一个beanhold
//heanhold其实就是一个 beanname和BeanDefinition的映射
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
//创建代理对象
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 实际上DefaultListableBeanFactory内部维护一个Map<String, BeanDefinition>
//类型变量beanDefinitionMap,
//用于保存注bean定义信息(beanname 和 beandefine映射)
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
5. ClassPathBeanDefinitionScanner
ClassPathBeanDefinitionScanner
是一个扫描指定类路径中注解Bean定义的扫描器,在初始化的时候,会初始化一些需要被扫描的注解,初始化用于加载包下的资源loader
。
AnnotatedBeanDefinitionReader
和 ClassPathBeanDefinitionScanner
是Spring上下文初始化的起点,很多预加载的类会在spring接下来初始化发挥重要作用。
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) {
//重点就是将扫描的bean放进来
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
//拿到Scope元数据
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
//生成beanName 首字母小写
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
//添加bean的定义信息
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
//如果是实现注解的beandefinition,然后把注解解析成属性
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
//检查bean
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//把Bean注册到factory
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
- BeanDefinitionHolder
//BeanDefinitionHolder是BeanDefinition的持有者
//BeanDefinitionHolder中三个属性
private final BeanDefinition beanDefinition;
private final String beanName;
@Nullable
private final String[] aliases;
- findCandidateComponents
findCandidateComponents
是ClassPathScanningCandidateComponentProvider
提供的
//找到包下的组件
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
// CandidateComponentsIndex是Spring5提供的优化扫描的功能
// 显然这里编译器我们没有写META-INF/spring.components索引文件,
// 所以此处不会执行Spring5 的扫描方式
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
//spring5优化方案
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
//spring5之前的方式
return scanCandidateComponents(basePackage);
}
}
- scanCandidateComponents (important)
scanCandidateComponents
是ClassPathScanningCandidateComponentProvider
提供的
//扫描此包,然后返回此包下的所有的Bean的set集合
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
//根据指定包名,生成包搜索路径
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//加载资源路径下的所有class,转化为resource[]
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
//日志方面 后面将删除掉所有日志信息
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (Resource resource : resources) {
//resource必须是可读
if (resource.isReadable()) {
try {
//读取类的注解信息和类信息,将信息储存到MetadataReader
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//通过TypeFilters过滤排除组件
if (isCandidateComponent(metadataReader)) {
//将符合条件的类转化成BeanDefinition
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
//再次判断是否为实体类,或者抽象类中有@Lookup
if (isCandidateComponent(sbd)) {
candidates.add(sbd);
}
}
}
}
}
}
return candidates;
}
- postProcessBeanDefinition
protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
//执行默认的信息
beanDefinition.applyDefaults(this.beanDefinitionDefaults);
//自动DI,匹配路径
if (this.autowireCandidatePatterns != null) {
beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
}
}
//AbstractBeanDefinition中实现的方法
public void applyDefaults(BeanDefinitionDefaults defaults) {
setLazyInit(defaults.isLazyInit());
setAutowireMode(defaults.getAutowireMode());
setDependencyCheck(defaults.getDependencyCheck());
setInitMethodName(defaults.getInitMethodName());
setEnforceInitMethod(false);
setDestroyMethodName(defaults.getDestroyMethodName());
setEnforceDestroyMethod(false);
}
6. 感想
AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner两个起点来,个人感觉从ClassPathBeanDefinitionScanner出发更好理解Ioc容器。Spring的架构庞大,但是基本上每个类的设计都很巧妙,符合单一职责原则。总而言之,复杂但不冗杂。
7. 参考
https://www.cnblogs.com/ashleyboy/p/9662119.html
https://cloud.tencent.com/developer/article/1497799
http://cmsblogs.com/?p=4026
持续