我们知道,当:
AnnotationConfigApplicationContext al=new AnnotationConfigApplicationContext(appconfig.class);
//appconfig这个类是个spring配置类,加了@Configuration,@ComponentScan("packgename")这两个注解。
此方法初始化了spring容器
下面一探源码:
/**
* 这个构造方法需要传入一个被javaconfig注解了的配置类
* 然后会把这个被注解了javaconfig的类通过注解读取器读取后继而解析
* Create a new AnnotationConfigApplicationContext, deriving bean definitions
* from the given annotated classes and automatically refreshing the context.
* @param annotatedClasses one or more annotated classes,
* e.g. {@link Configuration @Configuration} classes
*/
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//annotatedClasses appconfig.class
//这里由于他有父类,故而会先调用父类的构造方法,然后才会调用自己的构造方法
//在自己构造方法中初始一个读取器和扫描器
this();
register(annotatedClasses);//方法一
refresh();//方法二
}
先初始化父类的构造器,注意父类GenericApplicationContext的无参构造器是实例化BeanFactory
DefaultListableBeanFactory这个类就是spring的bean工厂
/**
* Create a new GenericApplicationContext.
* @see #registerBeanDefinition
* @see #refresh
* 一个工厂
*/
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
然后this()调用自己的无参构造,无参构造代码如下:
/**
* 初始化一个bean的读取和扫描器
* 何谓读取器和扫描器参考上面的属性注释
* 默认构造函数,如果直接调用这个默认构造方法,需要在稍后通过调用其register()
* 去注册配置类(javaconfig),并调用refresh()方法刷新容器,
* 触发容器对注解Bean的载入、解析和注册过程
* 这种使用过程我在ioc应用的第二节课讲@profile的时候讲过
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
/**
* 父类的构造方法
* 创建一个读取注解的Bean定义读取器
* 什么是bean定义?BeanDefinition
*/
this.reader = new AnnotatedBeanDefinitionReader(this);
//可以用来扫描包或者类,继而转换成bd
//但是实际上我们扫描包工作不是scanner这个对象来完成的
//是spring自己new的一个ClassPathBeanDefinitionScanner
//这里的scanner仅仅是为了程序员能够在外部调用AnnotationConfigApplicationContext对象的scan方法
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
首先看看构造方法里的第一个方法
this.reader = new AnnotatedBeanDefinitionReader(this);这句代码,构造方法参数是BeanDefinitionRegistry,而传的是this,表示AnnotationConfigApplicationContext是BeanDefinitionRegistry的子类。
AnnotatedBeanDefinitionReader这个类是BeanDefinition读取器,给它一个java类,它会解析成描述这个类的BeanDefinition,但是这个类只会解析加了注解的类,下面查看该方法的调用链:
/**
* 这里的BeanDefinitionRegistry registry是通过在AnnotationConfigApplicationContext
* 的构造方法中传进来的this
* 由此说明AnnotationConfigApplicationContext是一个BeanDefinitionRegistry类型的类
* 何以证明我们可以看到AnnotationConfigApplicationContext的类关系:
* GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry
* 看到他实现了BeanDefinitionRegistry证明上面的说法,那么BeanDefinitionRegistry的作用是什么呢?
* BeanDefinitionRegistry 顾名思义就是BeanDefinition的注册器
* 那么何为BeanDefinition呢?参考BeanDefinition的源码的注释
* @param registry
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
再往里:
/**
* Create a new {@code AnnotatedBeanDefinitionReader} for the given registry and using
* the given {@link Environment}.
* @param registry the {@code BeanFactory} to load bean definitions into,
* in the form of a {@code BeanDefinitionRegistry}
* @param environment the {@code Environment} to use when evaluating bean definition
* profiles.
* @since 3.1
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
// 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, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}