前置知识:
我们知道BeanFactory是用来生产bean的工厂,它是一个接口,他还有子接口ApplicationContext,提供更丰富的功能,来初始化Spring的上下文环境。
// 通过加载配置类,初始化spring的上下文环境(全注解开发)
AnnotationConfigApplicationContext context =
new
AnnotationConfigApplicationContext(AppContextConfig.class);
// 从IOC容器获取bean
context.getBean("userServiceImpl", UserService.class);
AnnotationConfigApplicationContext(AppContextConfig.class)
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
// 先调用了自己的空参构造器,在自己的空参构造器中会调用父类GenericApplicationContext的空参构造器
// 在父类的空参构造器中对beanFactory,进行了初始化
this();
// 注册该配置类
this.register(componentClasses);
// 刷新*************这才是主要方法**************
this.refresh();
}
GenericApplicationContext(),父类空参构造器
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
// bean工厂,也就是说bean工厂实际上是应用上下文的一个属性
// 但应用上下文和bean工厂又同时实现了BeanFactory接口
private final DefaultListableBeanFactory beanFactory;
......(省略了一些属性)
public GenericApplicationContext() {
this.customClassLoader = false;
this.refreshed = new AtomicBoolean();
// 创建bean工厂对象
this.beanFactory = new DefaultListableBeanFactory();
}
......
}
AnnotationConfigApplicationContext()本类的空参构造器
// 可以看到AnnotationConfigApplicationContext它不仅是一个应用上下文,它的父类GenericApplicationContext还实现了BeanDefinitionRegistry接口,所以他也是一个BeanDefinition的注册器,什么是BeanDefinition?(往下看)
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
// spring应用上下文中的读取器
private final AnnotatedBeanDefinitionReader reader;
// spring应用上下文中的扫描器
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext() {
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
// 初始化一个读取器,传入了上下文自己
// 首先我们要知道,spring除了我们自己定义的bean之外,也有一些内置的bean,用来辅助我们自定义bean的生产(可以理解为工厂中的工具、原料)那么此方法中就是注册了spring的内置bean
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
// 初始化一个扫描器,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的,所以不做分析
this.scanner = new
ClassPathBeanDefinitionScanner(this);
}
.......
}
BeanDefinition是什么?
它是一个描述bean的类,就比如说:该bean对应的类的全类名是什么,该bean的beanName(就是xml文件中那个id),该bean是否单例......我们最终实例化对象,就是跟据这个BeanDefinition中的描述信息进行的。
我们可以看一下beanDefinition的内部结构:
AnnotatedBeanDefinitionReader(this),这里的this就是我们new的annotationConfigApplicationContext对象
public class AnnotatedBeanDefinitionReader {
// 读取器也有一个属性是BeanDefinition的注册器
private final BeanDefinitionRegistry registry;
......(省略了一些属性)
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
this.beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
// 设置当前上下文对象作为读取器的注册器
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, (ResourceLoader)null);
// 注册各种处理器,registerAnnotationConfigProcessors方法中又调用了registerAnnotationConfigProcessors方法,这个方法中就是各种处理器的注册了,我们以一个为例来看
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
.......
}
registerAnnotationConfigProcessors(registry, (Object)null)
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
.......
RootBeanDefinition def;
if(!registry.containsBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor")) {
// 判断ConfigurationAnnotationProcessor处理器对应的beanDefinition是不是已经存在了,如果不存在就new一个(RootBeanDefinition是BeanDefinition的子类),并将beanClass设置为ConfigurationClassPostProcessor.class,实际上就是new一个对ConfigurationClassPostProcessor内置bean的描述对象。
def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// 开始注册bean
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));
}
......
}
registerPostProcessor()
private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
// 给bean definition设置了一个角色,表明是内置bean
/**
int ROLE_APPLICATION = 0; 应用程序主要部分角色
int ROLE_SUPPORT = 1; 这个 Bean 来自于用户配置。
int ROLE_INFRASTRUCTURE = 2; 基础设施,表明是spring内置的bean
**/
definition.setRole(2);
// 此处开始真正的注册bean,但是这是一个BeanDefinition的抽象方法,需要调用它的实现类中的方法,他有三个实现了此方法的类,我们刚刚在调用register的父类空构造器时,造了一个DefaultListableBeanFactory对象,所以自然是调用该bean工厂的注册方法了。
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
我们刚刚一直在谈到注册bean,实际上就是将内置bean对应的beanDefinition保存到bean工厂中。那为什么要保存beanDefinition呢?因为Spring是跟据beanDefinition中对bean的描述,来实例化对象的,就算自己定义的bean也是要被解析成一个beanDefinition并注册的。
registerBeanDefinition(beanName, definition)
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
......
// 用来保存BeanName对应的BeanDefinition对象
private final Map<String, BeanDefinition> beanDefinitionMap;
// 保存beanName
private volatile List<String> beanDefinitionNames;
......
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
......
// 提取两行核心代码
// 把beanName作为key,beanDefinition作为value放入Map中
this.beanDefinitionMap.put(beanName, beanDefinition);
// 把beanName放到list中
this.beanDefinitionNames.add(beanName);
......
}
我们来看一下现在的beanDefinitionMap与beanDefinitionNames的内部结构:
一个内置bean已经注册完成,它会接连注册好几个内置bean,都是用同样的方法,注册完成后,AnnotatedBeanDefinitionReader(this)方法,我们就分析完成了。
回到register(componentClasses)方法
// 可以看出,这里传入的是配置类数组
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register").tag("classes", () -> {
return Arrays.toString(componentClasses);
});
// 主要方法:又调用了读取器的注册方法,去注册配置类;此方法中会循环遍历数组,调用读取器的registerBean方法注册每个配置bean,registerBean方法中又调用了doRegisterBean方法
this.reader.register(componentClasses);
registerComponentClass.end();
}
registerBean(Class<?> beanClass)
public void registerBean(Class<?> beanClass) {
// 可以看到,注册bean时,除了beanClass,其他都是null
this.doRegisterBean(beanClass, (String)null, (Class[])null, (Supplier)null, (BeanDefinitionCustomizer[])null);
}
doRegisterBean()
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
// 生成配置bean的BeanDefinition,前面已经说过了BeanDefinition就是用来描述bean的(抽象的说就是bean定义),从下面的构造器中可以看出,不仅设置了BeanClass为当前配置类,还获取了该类上注解元信息,通过metadata对象,就可以获取到类上的注解信息了
/**
public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
this.setBeanClass(beanClass);
this.metadata = AnnotationMetadata.introspect(beanClass);
}
**/
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
//判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就不会被解析注册
// 这里提到了bean的解析,我们知道,刚刚生成的beanDefinition我们仅仅设置了beanClass为当前配置类,还没有解析bean,给beanDefinition的其他描述bean的属性设置值(比如是否单例.....),接下来就是做这件事
if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
abd.setInstanceSupplier(supplier);
//解析bean的作用域,如果没有设置的话,默认为单例
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 设置beanName,判断如果用户自己设置了name就用自定义的,没有设置就将类名首字母小写,作为beanName,默认传入的是null
String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
//解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,Description,从刚刚设置的metadata中去获取
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
int var10;
int var11;
// 注解处理(限定符处理),qualifiers是一个注解数组,如果我们以常规方式 AnnotationConfigApplicationContext context =
// new AnnotationConfigApplicationContext(AppContextConfig.class);去初始化spring,qualifiers就是null,如果以spring提供的其他特殊方式去注册,就可以传入了。
if (qualifiers != null) {
Class[] var9 = qualifiers;
var10 = qualifiers.length;
for(var11 = 0; var11 < var10; ++var11) {
Class<? extends Annotation> qualifier = var9[var11];
// 解析注解数组中的注解,重新设置beanDefinition的相应属性
if (Primary.class == qualifier) {
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
BeanDefinitionCustomizer[] var13 = customizers;
var10 = customizers.length;
for(var11 = 0; var11 < var10; ++var11) {
BeanDefinitionCustomizer customizer = var13[var11];
customizer.customize(abd);
}
}
// 把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 将配置类的beanDefinition注册到bean工厂中,与前面内置bean的注册相同,就是将beanName与baenDefinition封装到Map中,将beanName放到list中。Map与list都是bean工厂DefaultListableBeanFactory所维护的属性。
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
至此,我们的配置类就注册完成了,我们看一下现在的beanDefinitionMap与beanDefinitionNames的内部结构:(自己想看,可以打断点,加上断点条件为beanName.equals("自己配置类名首字母小写"))
总结:上述 this()和this.register(componentClasses)方法中就是将内置bean和我们传的配置bean的beanDefinition进行了注册,还没处理标记了@Component等注解的自定义bean。
下一篇,refresh()......
如有问题欢迎指正讨论